Home > Back-end >  Where the time coming from when converting date string without any time in to Date() in swift?
Where the time coming from when converting date string without any time in to Date() in swift?

Time:01-12

I'm using this extension to convert a string containing date to Date() object:

extension String {

  func toDate() -> Date?{
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "dd/MM/YYYY"
    let date = dateFormatter.date(from: self)
    return date
   }
}

the result always containing a time in it. I'm curious where is the time coming from, why it is not all zero?

print("11/12/2021".toDate())

result is ->

2020-12-19 21:00:00 0000

In the time that I run the code, it is showing 21:00:00, so why it is 21? I believe It is not related to my time because I run it at different times.

CodePudding user response:

A Date object indicates an instant in time anywhere on the planet, independent of time zone.

A DateFormatter can convert a String to a Date (or a Date to a String, but ignore that for now). When it converts a String to a Date, it may make assumptions about the time of day if that is not included in the String. I believe it assumes that the time is midnight (00:00:00) in the date formatter's time zone. (And by the way, midnight is the starting point of a day, so midnight is zero hours/minutes/seconds into the day. Essentially midnight IS zeros for time.)

So when you call your String extension to convert "11/12/2021" to a Date, the extension creates a DateFormatter which defaults to the device time zone. It creates a Date assuming Midnight in the local time zone.

When you print that date, it gets displayed in GMT.

It looks like your format string has problems though. You're getting the wrong year and month. I think you must be using the wrong month or day string in your formatter. (I always have to look those up when I use them.)

Edit:

You likely want a format string of "MM-dd-yyyy"

(2-digit month, 2-digit day of month, and 4-digit year.)

Lower-case "m" or "MM" is minutes. Upper-case "Y" is for "week of year" based calendars, which you probably don't want.

Try this code:


  func toDate() -> Date?{
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "MM-dd-yyyy"
    let posixLocale = Locale(identifier: "en_US_POSIX")
    dateFormatter.locale =  posixLocale
    let date = dateFormatter.date(from: self)
    return date
   }
}

And to use it:

    let dateString = "12/11/2021"
    let date = dateString.toDate()
    print(date)
    if let date = date {
        let convertedDateString = DateFormatter.localizedString(from: date, dateStyle: .medium, timeStyle: .medium)
        print(convertedDateString)
    } else {
        print("Can't convert \(dateString) to a date")
    }

That displays "Dec 11, 2021 at 12:00:00 AM" in my US locale (US Date formatting.) Note that since I use the DateFormatter class method localizedString(from:dateStyle:timeStyle:) I see midnight as the displayed time (The time you get from a DateFormatter when you don't specify a time, but displayed in the local time zone.)

CodePudding user response:

The answer is:

when we are converting a string to a Date Object the important part is the time zone that we are converting it to.

for example, if you convert your string date to a UTC time zone when you want to bring it back you have to set the time zone of the date to UTC.

    let dateFormatter = DateFormatter()
    dateFormatter.timeZone = TimeZone(identifier: "UTC")

so this is the reason why when we are printing the Date() object it is deferred from our string date.

extension String {

  func toDate() -> Date?{
     let dateFormatter = DateFormatter()
     dateFormatter.dateFormat = "mm-dd-yyyy"
     let date = dateFormatter.date(from: self)
     return date
  }
}

extension Date {

   func toString() -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "mm-dd-yyyy"
    return dateFormatter.string(from: self)
   }
}

let stringDate = "01-12-2021"
let date = "01-12-2021".toDate()
let convertBack = date?.toString()

print("(\(stringDate)) -> (\(date!)) -> (\(convertBack!))")

and the result is:

(01-12-2021) -> (2021-01-11 21:01:00 0000) -> (01-12-2021)

so at the end when we convert back the Date object it will be the same. because that 2 dateFormatter in the extensions are using the default time zone. and if you want to specify a specific time zone you have to declare it in converting from and to string together.

  •  Tags:  
  • Related