0

When trying to get the latest possible date for a day that is not the day after (i.e. 2015-03-17 23:59:59.999...), I should be able to add 1 day to the date, and then subtract a unit of least precision from the timeInterval double. This should yield the correct date, however as you can see from below, the day of that date is not consistent.

let calendar = NSCalendar.currentCalendar()
var comps = NSDateComponents()
comps.day = 17
comps.month = 3
comps.year = 2015

// Get today, tomorrow, and endOfToday
let today = calendar.dateFromComponents(comps)!
let tomorrow = calendar.dateByAddingUnit(.CalendarUnitDay, value: 1, toDate: today, options: nil)!
let intervalToday = today.timeIntervalSinceReferenceDate // 448243200
let intervalTomorrow = tomorrow.timeIntervalSinceReferenceDate // 448329600
// Get interval immediately before intervalTomorrow (subtract ULP - unit of least precision)
// nextafter intervalTomorrow in the direction of intervalToday
let endOfTodayInterval = nextafter(intervalTomorrow, intervalToday) // 448329599.9999999
let endOfToday = NSDate(timeIntervalSinceReferenceDate: endOfTodayInterval)

println(today) // 2015-03-17 00:00:00 +0000
println(tomorrow) // 2015-03-18 00:00:00 +0000
println(endOfToday) // 2015-03-18 00:00:00 +0000 !!! Hmm... should be 2015-03-17 23:59:59 +0000

// So... what day is the endOfToday!? 18th or 17th?
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "d"
dateFormatter.stringFromDate(endOfToday) // 18
calendar.component(.CalendarUnitDay, fromDate: endOfToday) // 17
// Hmm...

Does anyone know what exactly is going on here, and why the date formatter and calendar date components don't agree?

Please note: There are valid reasons this value needs to be 1 unit of least precision lower than the next day. I am aware that I could just subtract 1 second, however that is not what is being questioned. What is in question is why the date formatter believes the day of the date below is 18 when it should be 17.

Michael Waterfall
  • 20,497
  • 27
  • 111
  • 168
  • I cannot subtract one second as the date needs to be the closest possible value to the next day for other reasons. The only issue I have is that the date formatter is not correctly displaying the date, and I don't believe it should be rounding up any dates as that yields an incorrect date string. – Michael Waterfall Mar 17 '15 at 12:41
  • How do you know what an ULP is to an NSDate? The value is not necessarily stored in floating point. – Hot Licks Mar 17 '15 at 12:44
  • 1
    @HotLicks NSTimeInterval a double, i.e. an IEEE754 64-bit float – Michael Waterfall Mar 17 '15 at 12:46
  • 1
    @MartinR Ah, interesting... that'll be it! – Michael Waterfall Mar 17 '15 at 12:48
  • @MartinR Thanks for that, didn't spot that question. Looks like I need update all my date formatting methods to floor the time interval! – Michael Waterfall Mar 17 '15 at 12:51
  • I don't know what sized time interval an `NSTimeInterval`'s ULP can represent, but it's probably extremely small, so I expect the date formatter is rounding up. – JeremyP Mar 17 '15 at 12:54
  • What NSTimeInterval represents and what NSDate represents are two different things. NSTimeInterval is just an convenient externalization of the internal value in NSDate, and is very likely approximate. – Hot Licks Mar 17 '15 at 13:05
  • @HotLicks that could possibly be true, I've no idea what the internals of NSDate are. If that is the case, is it possible at all to get the date that is the smallest possible difference from another date? – Michael Waterfall Mar 17 '15 at 13:13
  • @HotLicks although saying that, with the above example, endOfToday is indeed less than tomorrow. And the date component returns 17, so it appears that it is correct. So the question is really, does the NSDate offer greater sub-second precision an the time interval double. – Michael Waterfall Mar 17 '15 at 13:14
  • Actually `NSDate(timeIntervalSinceReferenceDate: x).timeIntervalSinceReferenceDate` seems to be *exactly equal* to `x` , so I do not think that NSDate loses the precision. The precision is lost in the ICU date formatting routines used by NSDateFormatter/NSCalendar. – Martin R Mar 17 '15 at 13:15

0 Answers0