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

  1. i creating date offset particular date (self in case in nsdate() extension) using nscalendar.datebyaddingunit(..., value:x, ...)
  2. i difference "fromdate" (created date or self) "todate" (current time nsdate()) using nscalendar.components(..., fromdate, todate, ....).minute
  3. if x>0, answer in step above x-1. if x<0, answer x. x defined in step 1 above.
  4. 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.
  5. 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

Popular posts from this blog

facebook - android ACTION_SEND to share with specific application only -

python - Creating a new virtualenv gives a permissions error -

javascript - cocos2d-js draw circle not instantly -