3

I have just migrated my app's code to Swift 3 and I am getting this really annoying issue with the DateFormatter(formerly NSDateFormatter) that I did not get with Swift 2 or earlier.

The issue is that I need to convert a string to a Date object and my code to do so is something like,

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let dateStr1 = "2017-02-22"
let date1 = dateFormatter.date(from: dateStr1)

Now this works fine and as expected in Xcode playgrounds but when I try to run it from my app, date1 returns 2017-02-21 13:00:00 +0000 i.e. a day in the past and I need date1 to be 2017-02-22 fyi, I am in Australia where I am doing this development.

I am getting the date string from my app's UI, and from the UI it's 2017-02-22 so I need to covert that string to a Date (or NSDate) object in Swift.

I have tried setting the TimeZone and Locale for the DateFormatter,

dateFormatter.timeZone = TimeZone(identifier: TimeZone.current.identifier)

dateFormatter.locale = Locale.init(identifier: Locale.current.identifier)

but still no luck?

I have also tried creating the Date from Calendar components like,

var dateComponents = DateComponents()
var day = "22"
var month = "02"
var year = "2017"
dateComponents.day = Int(day)!
dateComponents.year = Int(year)!
print(TimeZone.current)
dateComponents.timeZone = TimeZone.current
dateComponents.month = Int(month)!
let userCalendar = Calendar.current
let date1 = userCalendar.date(from: dateComponents)

But still not getting the right date i.e. getting 2017-02-21 instead of 2017-02-22 I have looked at some of the other SO questions like

How do you create a swift Date object

Converting date between timezones swift

amongst others. Any ideas of how I can achieve the result I want? this code was working completely fine prior to Swift.

Community
  • 1
  • 1
cptdanko
  • 812
  • 2
  • 13
  • 22
  • Why do you think there is anything wrong with the first 4 lines code in your question? It's fine and correct. – rmaddy Feb 22 '17 at 04:47
  • 1
    Midnight on Feb 22 in Australia is 13:00 on the 21st UTC time. There's nothing wrong. – rmaddy Feb 22 '17 at 04:49
  • Fair enough! I have edited the question to make the issue more clear. – cptdanko Feb 22 '17 at 05:00
  • 1
    Again, there is nothing wrong with your code. The only confusion is your understanding of the output of printing/logging a `Date` object. Now having said that, your date string is being processed in the user's local time. If you want the date string to be processed as UTC time or some other specific timezone, then you need to set the date formatter's timezone as needed. But if local time is correct, then your code is correct as-is. – rmaddy Feb 22 '17 at 05:04
  • ok so the thing is that I need an (NS) Date() object with 2017-02-22 so I can do some processing app logic based on that. With the code I pasted I am not getting that. So basically want a Date() object with 2017-02-22. I cannot get that? I thought using Calendar.current.date(from: components) would help me get that, but that wasn't successful either? – cptdanko Feb 22 '17 at 05:30
  • That's just it. You are getting a date of 2017-02-22 *localtime*. When you print it, iOS simply formats your date into UTC time for display. So again, if you want your date to be interpreted as local time, then your code is fine as-is. – rmaddy Feb 22 '17 at 05:34
  • There is nothing in wrong. when you convert "date1" to string getting right date. – Nidhi Patel Feb 22 '17 at 05:38
  • I have edited my question and I just want to know how can I convert it the date to that of the users local timezone. So convert from UTC to AEDT timezone? or whatever timezone it is on the users device. – cptdanko Feb 23 '17 at 01:59
  • Also regarding comment, my code is not interpreted as local time. Whether I print it or step through the code the date is the UTC date and not local date plus the app is not behaving correctly. – cptdanko Feb 23 '17 at 12:28
  • @cptdanko did you solve your issue? – user1960169 Jul 29 '17 at 04:04

1 Answers1

2

As maddy pointed out in the comments, Xcode is showing you the date in its "raw form" of Universal Timezone - UTZ - (also called Greenwich Meantime).

To get the date presented in another timezone you need to use the DateFormatter again.

So:

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let dateStr1 = "2017-02-22"
let date1: Date = dateFormatter.date(from: dateStr1)!

print("\(date1)")
print("\(dateFormatter.string(from: date1))")

Gives you:

Print screen of code in playground with output.

I'm running this code in Perth, Western Australia (i.e. UTZ+8) - therefore when I convert 22-Feb-2017 into a date it is stored as 21-Feb-2017 UTZ, but if I present it back with a DateFormatter from my locale I get midnight, 22-Feb-2017.

Community
  • 1
  • 1
Rob Paterson
  • 2,493
  • 3
  • 21
  • 21