ios - NSCalendar.components().minute returning inconsistent values -
original problem encountered during post, testing , code in link below https://stackoverflow.com/questions/27339072/working-with-nsdate-components-in-swift/30822018#30822018
here minimal test-case
- i creating date offset particular date (self in case in nsdate() extension) using nscalendar.datebyaddingunit(..., value:x, ...)
- i difference "fromdate" (created date or self) "todate" (current time nsdate()) using nscalendar.components(..., fromdate, todate, ....).minute
- if x>0, answer in step above x-1. if x<0, answer x. x defined in step 1 above.
- this has potential cause bugs in applications filter events using human readable attributes such events in past 3 hrs since 180 minutes not 3 hours due behavior.
- this not bug in step 1 since date prints correctly seen in printout @ end of post.
is there option in nscalendar.components missing or bug?
here code.
// // nsdatetest.swift // nsdatetestcase // // created jitendra kulkarni on 6/13/15. // import foundation public extension nsdate { func xmins(x:int) -> nsdate { return nscalendar.currentcalendar().datebyaddingunit(.calendarunitminute, value: x, todate: self, options: nil)! } var hoursfromtoday: int{ var fromdate: nsdate = self var todate: nsdate = nsdate() var sign: int = -1 (fromdate,todate, sign) = self.sanitizeddates() return (sign * nscalendar.currentcalendar().components(.calendarunithour, fromdate: fromdate, todate: todate, options: nil).hour) } var minsfromtoday: int{ var fromdate: nsdate = self var todate: nsdate = nsdate() var sign: int = 1 (fromdate,todate) = self.sanitizeddates() return ( sign * nscalendar.currentcalendar().components(.calendarunitminute, fromdate: fromdate, todate: todate, options: nil).minute) } //date comparisons //https://stackoverflow.com/questions/26198526/nsdate-comparison-using-swift func isgreaterthandate(datetocompare : nsdate) -> bool { //declare variables var isgreater = false //compare values if self.compare(datetocompare) == nscomparisonresult.ordereddescending { isgreater = true } //return result return isgreater } // date printing conversions var timedaymonthyear: string { let datemonthyearformatter: nsdateformatter = nsdateformatter() let currentlocale: nslocale = nslocale.currentlocale() let datemonthyearformatstring: nsstring! = nsdateformatter.dateformatfromtemplate("edmmmyyyy' ' hh':'mm",options: 0, locale: currentlocale) datemonthyearformatter.dateformat = datemonthyearformatstring as! string return datemonthyearformatter.stringfromdate(self) } private func sanitizeddates() -> (fromdate: nsdate, todate: nsdate) { var todate: nsdate = self var fromdate: nsdate = nsdate() if(todate.isgreaterthandate(fromdate)) { // todate = todate.xmins(1) // uncomment make answer work } return (fromdate,todate) } static func test (mins: int = 0) { nslog("****************** start testing of nsdate **************************") nslog("inputs: mins: \(mins)") var today = nsdate() nslog("today is: \(today.timedaymonthyear)") var minsfromtoday = today.xmins(mins) nslog("** date created \(mins) minutes today is: \(minsfromtoday.timedaymonthyear)") nslog("minsfromtoday returns: \(minsfromtoday.minsfromtoday)"); nslog("hoursfromtoday returns: \(minsfromtoday.hoursfromtoday)"); nslog("__________________ end testing of nsdate _________________________") } }
here result of nsdate(60) followed nsdate(-60). *error. if remove comments 1 commented line in sanitizeddate(), expected result.
2015-06-13 14:56:44.877 nsdatetestcase[23136:1150501] ****************** start testing of nsdate ************************** 2015-06-13 14:56:44.878 nsdatetestcase[23136:1150501] inputs: mins: 60 2015-06-13 14:56:44.882 nsdatetestcase[23136:1150501] today is: sat, jun 13, 2015, 14:56 2015-06-13 14:56:44.883 nsdatetestcase[23136:1150501] ** date created 60 minutes today is: sat, jun 13, 2015, 15:56 2015-06-13 14:56:44.883 nsdatetestcase[23136:1150501] minsfromtoday returns: 59 // *error should 60 2015-06-13 14:56:44.884 nsdatetestcase[23136:1150501] hoursfromtoday returns: 0 // *error should 1 2015-06-13 14:56:44.884 nsdatetestcase[23136:1150501] __________________ end testing of nsdate _________________________ 2015-06-13 14:56:44.884 nsdatetestcase[23136:1150501] ****************** start testing of nsdate ************************** 2015-06-13 14:56:44.884 nsdatetestcase[23136:1150501] inputs: mins: -60 2015-06-13 14:56:44.885 nsdatetestcase[23136:1150501] today is: sat, jun 13, 2015, 14:56 2015-06-13 14:56:44.885 nsdatetestcase[23136:1150501] ** date created -60 minutes today is: sat, jun 13, 2015, 13:56 2015-06-13 14:56:44.886 nsdatetestcase[23136:1150501] minsfromtoday returns: -60 2015-06-13 14:56:44.886 nsdatetestcase[23136:1150501] hoursfromtoday returns: -1 2015-06-13 14:56:44.893 nsdatetestcase[23136:1150501] __________________ end testing of nsdate _________________________
here code based on kurt's answer below. notice xfromtoday api has changed input "today":
// // nsdatetest.swift // nsdatetestcase // // created jitendra kulkarni on 6/13/15. // import foundation public extension nsdate { func xmins(x:int) -> nsdate { return nscalendar.currentcalendar().datebyaddingunit(.calendarunitminute, value: x, todate: self, options: nil)! } func hoursfromtoday(today: nsdate) -> int { var fromdate: nsdate = self var todate: nsdate = today return (-nscalendar.currentcalendar().components(.calendarunithour, fromdate: fromdate, todate: todate, options: nil).hour) } func minsfromtoday(today: nsdate) -> int { var fromdate: nsdate = self var todate: nsdate = today return (-nscalendar.currentcalendar().components(.calendarunitminute, fromdate: fromdate, todate: todate, options: nil).minute) } //date comparisions //https://stackoverflow.com/questions/26198526/nsdate-comparison-using-swift func isgreaterthandate(datetocompare : nsdate) -> bool { //declare variables var isgreater = false //compare values if self.compare(datetocompare) == nscomparisonresult.ordereddescending { isgreater = true } //return result return isgreater } // date printing converstions var timedaymonthyear: string { let datemonthyearformatter: nsdateformatter = nsdateformatter() let currentlocale: nslocale = nslocale.currentlocale() let datemonthyearformatstring: nsstring! = nsdateformatter.dateformatfromtemplate("edmmmyyyy' ' hh':'mm",options: 0, locale: currentlocale) datemonthyearformatter.dateformat = datemonthyearformatstring as! string return datemonthyearformatter.stringfromdate(self) } static func test (mins: int = 0) { nslog("****************** start testing of nsdate **************************") nslog("inputs: mins: \(mins)") var today = nsdate() nslog("today is: \(today.timedaymonthyear)") var minsfromtoday = today.xmins(mins) nslog("** date created \(mins) minutes today is: \(minsfromtoday.timedaymonthyear)") //nslog("minsfromtoday returns: \(minsfromtoday.minsfromtoday)") nslog("minsfromtoday(today) returns: \(minsfromtoday.minsfromtoday(today))"); //nslog("hoursfromtoday returns: \(minsfromtoday.hoursfromtoday)") nslog("hoursfromtoday(today) returns: \(minsfromtoday.hoursfromtoday(today))"); nslog("__________________ end testing of nsdate _________________________") }
here output produced:
2015-06-13 16:23:55.362 nsdatetestcase[23758:1196619] ****************** start testing of nsdate ************************** 2015-06-13 16:23:55.363 nsdatetestcase[23758:1196619] inputs: mins: 60 2015-06-13 16:23:55.366 nsdatetestcase[23758:1196619] today is: sat, jun 13, 2015, 16:23 2015-06-13 16:23:55.367 nsdatetestcase[23758:1196619] ** date created 60 minutes today is: sat, jun 13, 2015, 17:23 2015-06-13 16:23:55.367 nsdatetestcase[23758:1196619] minsfromtoday(today) returns: 60 // now. 2015-06-13 16:23:55.367 nsdatetestcase[23758:1196619] hoursfromtoday(today) returns: 1 // now. 2015-06-13 16:23:55.367 nsdatetestcase[23758:1196619] __________________ end testing of nsdate _________________________ 2015-06-13 16:23:55.368 nsdatetestcase[23758:1196619] ****************** start testing of nsdate ************************** 2015-06-13 16:23:55.368 nsdatetestcase[23758:1196619] inputs: mins: -60 2015-06-13 16:23:55.368 nsdatetestcase[23758:1196619] today is: sat, jun 13, 2015, 16:23 2015-06-13 16:23:55.369 nsdatetestcase[23758:1196619] ** date created -60 minutes today is: sat, jun 13, 2015, 15:23 2015-06-13 16:23:55.370 nsdatetestcase[23758:1196619] minsfromtoday(today) returns: -60 2015-06-13 16:23:55.380 nsdatetestcase[23758:1196619] hoursfromtoday(today) returns: -1 2015-06-13 16:23:55.381 nsdatetestcase[23758:1196619] __________________ end testing of nsdate _________________________
you calling nsdate()
in 4 different places in code.
each 1 return current date , time when code executes, differ fractions of second.
i suspect want use 1 consistent value "today" in whole calculation. call nsdate()
once, @ start of code, store in variable, , refer variable consistently.
Comments
Post a Comment