Odd behaviour from RelativeDateTimeFormatter

I should preface my question by saying I love this formatter and the edge cases it handles for us, but I've found a case that seems odd to me. (all times are in the same time zone. let's go with Pacific) current time is 3:05pm, December 21

comparison time formatter output dec 20 @ 3:15pm 23 hours ago (great!) dec 20 @ 2:15pm yesterday (also great!) dec 19 @ 3:15pm yesterday (wait, wut?!)

If today is Dec 21, shouldn't yesterday be limited to Dec 20 00:00:00 - 23:59:59? I see three options:

  1. I'm using RelativeDateTimeFormatter incorrectly
  2. I'm misunderstanding the sematics of 'yesterday' ( is it correct to refer to 47 hours ago as yesterday?)
  3. RelativeDateTimeFormatter is misbehaving

all thoughts on this are welcome.foun

here is some playground code demonstrating this behaviour

let relativeDateFormatter: RelativeDateTimeFormatter = {
    let formatter = RelativeDateTimeFormatter()
    formatter.dateTimeStyle = .named
    return formatter
}()

func startDate(from dateText: String) -> Date {
    let formatter = DateFormatter()
    formatter.locale = Locale(identifier: "en_US_POSIX")
    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
    formatter.timeZone = .current
    return formatter.date(from: dateText)!
}

let myNow = startDate(from: "2022-12-21T23:05:00Z")
let almostTwoDaysAgo = myNow.addingTimeInterval(-(48 * 3600 - 600))

let relText = relativeDateFormatter.localizedString(for: almostTwoDaysAgo, relativeTo: myNow)
Answered by Claude31 in 740414022

Even

let almostTwoDaysAgo = myNow.addingTimeInterval(-(48 * 3600 - 1))

will return yesterday. Similarly

let almostTwoDaysAgo = myNow.addingTimeInterval(48 * 3600 - 1)

returns tomorrow, not in 2 days

RelativeDateTimeFormatter is not rounding but truncating:

.

I'm misunderstanding the sematics of 'yesterday' ( is it correct to refer to 47 hours ago as yesterday?)

I fear answer is yes

-1.9999 day is truncated 1 day, so yesterday.

  • What would you expect ?
  • rounding, so -1.999 would return -2, same as -1.51.
  • but then -1.51 days would be Dec 20 11:15
  • Do you want it to say 2 days ago ?

It is not considering that Dec 19 23:15 is 2 days before Dec 21 23:05

You could file a bug report for enhancement, at least on documentation.

looks like I didn't format my table very well. I'll try again here:

comparison time       formatter output 
dec 20 @ 3:15pm     23 hours ago (great!) 
dec 20 @ 2:15pm     yesterday (also great!)
dec 19 @ 3:15pm     yesterday (wait, wut?!)

Accepted Answer

Even

let almostTwoDaysAgo = myNow.addingTimeInterval(-(48 * 3600 - 1))

will return yesterday. Similarly

let almostTwoDaysAgo = myNow.addingTimeInterval(48 * 3600 - 1)

returns tomorrow, not in 2 days

RelativeDateTimeFormatter is not rounding but truncating:

.

I'm misunderstanding the sematics of 'yesterday' ( is it correct to refer to 47 hours ago as yesterday?)

I fear answer is yes

-1.9999 day is truncated 1 day, so yesterday.

  • What would you expect ?
  • rounding, so -1.999 would return -2, same as -1.51.
  • but then -1.51 days would be Dec 20 11:15
  • Do you want it to say 2 days ago ?

It is not considering that Dec 19 23:15 is 2 days before Dec 21 23:05

You could file a bug report for enhancement, at least on documentation.

Yes, it does look like a bug. I think that the .named style isn't properly falling back to a .numeric style when there's no suitable name, for some small-ish range of time intervals. Could you file a bug report with Feedback Assistant, and post the bug number here for reference, please?

Odd behaviour from RelativeDateTimeFormatter
 
 
Q