-2

Greetings there m'ladies, m'lords!

Long story short I have a helper struct where I have some helper functions for creating date formatters, Date objects and String representations of dates. I've debugged and narrowed it down to this:

func getFormattedString(from stringDate: String,
                                   with timeZoneID: String? = nil,
                                   appFormat appDateFormat: DateFormats = .api,
                                   apiFormat apiDateFormat: DateFormats = .api) -> String? {
        //this must use the default utc timezone so pass in the nil value here
        let apiDateFormatter = dateFormatter(with: apiDateFormat, timeZoneID: nil)
        if let utcDate = apiDateFormatter.date(from: stringDate) {
            let appDateFormatter = dateFormatter(with: appDateFormat, timeZoneID: timeZoneID)
            return appDateFormatter.string(from: utcDate)
        }
        return nil
    }

For the dateFormatter(with:) use this function:

enum DateFormats: String {
    case api = "YYYY-MM-dd HH:mm:ss"
    // more cases here
}

let utcTimeZone = TimeZone(abbreviation: "UTC")

func dateFormatter(with dateFormat: DateFormats = .api, timeZoneID: String?) -> DateFormatter {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = dateFormat.rawValue
        if let timeZoneID = timeZoneID {
            if let timezoneIdentifier = TimeZone(identifier: timeZoneID) {
                dateFormatter.timeZone = timezoneIdentifier
            } else if let abbreviatedTimezone = TimeZone(abbreviation: timeZoneID) {
                dateFormatter.timeZone = abbreviatedTimezone
            } else {
                dateFormatter.timeZone = utcTimeZone
            }
        } else {
            dateFormatter.timeZone = utcTimeZone
        }
        return dateFormatter
    }

Basically I get a string from the server and it is in UTC, so I create my Date object from that string in the UTC timezone. Then I'm creating another date formatter which this time uses the timezone that comes from the server. Everything's been going great so far, but I've recently come across a weird case.

Let's say we have the following strings from the "server": let start = "2021-12-25 00:00:00" let end = "2021-12-26 23:59:59"

When we're calling getFormattedString(from: start) it gives us a string that represents the same date (year, month and day), but if we're calling it for 26th of Dec of any year the string created by the date formatter will autoincrement the year from 2021 to 2022... I've seen this only happens for the following dates: from 26th to 31st of December, including 26 and 31. But for any other months this does NOT occur.

I'm really wondering if I've been doing something wrong from the very start or if this is indeed a very edge case bug?

I have to display dates and string dates based on the timezone of an event, combined with the fact that from the server we get UTC timezone based dates and there's a calendar which has to show everything from UTC to the event's correct timezone while also ensuring the whole calendar may change based on the user's current timezone. I know, working with dates is not pleasant, but thing is I'm 100% positive the code is working properly. I mean it's a feature that's been in production for years and no one ever rose this issue (thankfully that'a period where everyone's spending time not working, unlike me lol). Honestly, I don't even know how I've come across this super edge case...

Any help or suggestion would mean a lot. Thanks everyone in advance :)

  • 1
    YYYY means week of the year, you want yyyy for your api date format. – Joakim Danielson Oct 31 '21 at 17:34
  • M'lord, thank you so much. It works like a charm now. It seems someone changed the format string from "yyyy..." to "YYYY...". There are a lot more string formats and all of them use lowercased "y"s. Only this api case used uppercased letters (just the most important one) lol. I spent almost 3 days debugging this lmao. If I can ever repay you back good sir, do not hesitate, for I shall come and aid you in your endeavours as well. Have a great day m'lord! /bow – Sorin Miroiu Oct 31 '21 at 18:14

1 Answers1

0

The issue was the uppercased "YYYY", for there should be lowercased ones, as in "yyyy". The solution. Many thanks to m'lord Joakim.