Search code examples
iosswiftdatetimezoneswift4

Swift 4 wrong date and time


I am struggle with timezone because I tried to set time to midnight to 23:00:00, however, the result show start with 6am until 5am next day. I tried to set timezone to current, still same result. Here my code

let day1num = Int(todaynumber.string(from: Date()))! + 1
let day1start = Calendar.current.date(bySetting: .day, value: day1num, of: Date())
let day1end = Calendar.current.date(bySetting: .hour, value: 23, of: day1start!)
print("\(day1start!) to \(day1end!)")

I got result 2020-04-22 06:00:00 +0000 to 2020-04-23 05:00:00 +0000

I don't want 6am to 5am next day, I want result: 2020-04-22 00:00:00 +0000 to 2020-04-22 23:00:00 +0000

How can I solve it? Thanks!


Solution

  • Your issue is you're misunderstanding Date and how it prints to the console.

    Dates are representative of moments in time. Think of them as an Integer that represents the amount of time that has passed since a reference date. It's NOT a human-readable string. To convert a date to a human-readable string, you need to use a DateFormatter and make sure to set the timeZone of the date formatter to be the time zone in which you want the string to be representative of (it will default to the system's current time zone). The timeZone will impact what the resulting string is. For example, if you have a date formatter where the time zone is Pacific time, it might return a value like April 22, 2020 6:00 PM, but then if you change the time zone to mountain time and get the string from the date, it will return April 22, 2020 7:00 PM.

    When you print a Date instance to the console, the system formats it to be a human-readable string in the UTC time zone. If I'm doing my math correctly, you're in mountain time, which is why the value you're seeing logged is 6 hours ahead of the value you're expecting.

    If you want to see the date logged to the console as the user will see it, you should use a DateFormatter instance. It will default to use the user's system time zone, then use the Date value you've calculated to get the String representation of that date, and then log that String to the console, rather than the date itself.

    let formatter = DateFormatter()
    formatter.dateStyle = .medium // Customize as needed
    formatter.timeStyle = .medium // Customize as needed
    // formatter.timeZone = ... something else if you don't want to use the system time zone
    let day1StartAsString = formatter.string(from: day1start!)
    let day1EndAsString = formatter.string(from: day1end!)
    print("\(day1StartAsString) to \(day1EndAsString)")