0

As the title indicates I'm trying to get the start and end of month with a time component for December. I'm sure I'm missing something obvious related to TimeZones but I can't seem to get a same year for both dates in in PST time zone.

Here's how I get the start of month and day:

NOTE: If you try this in the swift REPL there's a bug that shows nil result even though the variables have a non-nil value, use print or debugPrint to show the value.

let cal = Calendar.current
let startOfMonth = cal.startOfDay(for: cal.date(from: DateComponents(year: 2020, month: 12, day: 1))!)

Here's how I calculate the end of day up to seconds:

let startOfNextMonth = cal.date(byAdding: DateComponents(month: 1), to: startOfMonth)!
let endOfMonth = cal.date(byAdding: DateComponents(second: -1), to: startOfNextMonth)!

By this point startOfMonth has the value: Optional(2020-12-01 08:00:00 +0000) and endOfMonth has a value of Optional(2021-01-01 07:59:59 +0000)

Which seems fine and dandy because times are printed in GMT (UTC) and if I subtract 8 hours endOfMonth it would end up like Optional(2020-12-31 23:59:59 +0000)

However the trouble comes when formatting the endOfMonth date, even If I set the TimeZone to "America/Los_Angeles" I still get the year value as 2021 and not as 2020, here's how I create my formatter:

let fmt = DateFormatter()
fmt.timeZone = .current // "America/Los_Angeles"
fmt.dateFormat = "d/Y"

fmt.string(from: endOfMonth!) // $R13: String = "31/2021"

What's going on?, wouldn't conversion to the default Time zone yield the year 2020?

Tristian
  • 3,406
  • 6
  • 29
  • 47
  • There are always many of those questions on turn of the year because the *misuse* of the `Y` year specifier has no effect in the rest of the year – vadian Jan 06 '21 at 10:29

1 Answers1

0

After setting the formatter dateStyle property to .long and obtaining the correct year printed (though not the format I wanted) I realized that the issue might be in the dateFormat.

After reading a bit more of the documentation, I found a link to the format specifiers

Eventually I found out that the Y specifier is essentially a "Week of Year" vs the y specifier which is "Year of Era".

Using the following fixed my issue:

let formatter = DateFormatter()
formatter.dateFormat = "d/y"
formatter.string(from: endOfMonth!) // $R1: String = "31/2020"
Tristian
  • 3,406
  • 6
  • 29
  • 47
  • If you want a fixed date format you should set the locale to "en_US_POSIX". From the docs: **If you're working with fixed-format dates, you should first set the locale of the date formatter to something appropriate for your fixed format. In most cases the best locale to choose is "en_US_POSIX", a locale that's specifically designed to yield US English results regardless of both user and system preferences.** – Leo Dabus Jan 06 '21 at 15:19