0

Before flagging this question as a duplicate, please read on.

I need to compare two NSDates. A date I get from a server with the current date.

From NSDate.date() I get this date 2014-09-25 12:48:23 +0000 which is wrong (the time part). I needed to add 5 hours to get the current time so I did the following.

let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd hh:mm:ss ZZZZZ"
let dateString = formatter.stringFromDate(NSDate.date())

The result is the correct date - 2014-09-25 06:21:56 +05:30

But there's a little hitch. This date is a String, not a NSDate. I need it to be a NSDate object to compare it with another date.

I tried converting it back like this,

let date = formatter.dateFromString(dateString)

And I get a wrong result - 2014-09-25 00:55:53 +0000. I tried passing the date string to a new NSDateFormatter to see if that works but again I still I get the wrong date.

My question is, how can I convert this date string to a NSDate object which also retains the correct time.

Thank you.

Isuru
  • 30,617
  • 60
  • 187
  • 303
  • http://stackoverflow.com/questions/24089999/how-do-you-create-a-swift-date-object – Kirit Modi Sep 25 '14 at 13:04
  • Probably you may forgot to set the time zone of dateFormatter? – Anil Varghese Sep 25 '14 at 13:04
  • See the NSDate uses a default timeZone(that is GMT) and to get time for a particular timeZone you can use the NSDateFormatter. In your case after you use NSDateFormatter (which by default will take your time zone and not GM) so will show different time then NSDate. – nikhil84 Sep 25 '14 at 13:05
  • @walle84 and @Anil, I specified the time zone `formatter.timeZone = NSTimeZone(name: "GMT")` but I still get the wrong date. – Isuru Sep 25 '14 at 13:11
  • 1
    not GMT, you have 5hrs difference no? So timezone will be GMT+5.00 – Anil Varghese Sep 25 '14 at 13:13
  • @Anil I changed it to this `formatter.timeZone = NSTimeZone.localTimeZone()` but still the wrong date is coming up. Am I missing something else? – Isuru Sep 25 '14 at 13:22
  • 1
    NSDate denotes an absolute point in time (counted in seconds since some reference date) and has no knowledge of time zones. Its *description* 2014-09-25 12:48:23 +0000 uses GMT, and this is *exactly* the same point in time as 2014-09-25 06:21:56 +05:30. So saying that the first is wrong and the second is correct that not make sense. – Martin R Sep 25 '14 at 13:38
  • I found [this](http://agilewarrior.wordpress.com/2012/06/27/how-to-convert-nsdate-to-different-time-zones/) article which includes a method which does what I needed. I posted its Swift translation as an answer. Thanks everyone for all the help. – Isuru Sep 25 '14 at 13:53

3 Answers3

2

You are thoroughly confused about NSDate.

An NSDate is a point in time. It has no time zone information. If we both call [NSDate date] right now, we will get the same NSDate, even when you are in India and I'm in the UK. That's intentional. It's the same time. The time displayed on my watch and on your watch is different, but NSDate is the same. You can't convert NSDate to an "Indian" date.

You use calendars and timezones to convert NSDates to strings that you display to a user, in the way your users expect it. That's what you have done. You got a string that makes sense to Indian users. If an Indian user types a time, you take that string and convert it to an NSDate. The NSDate will be in Universal time. If you and I both typed in the time on our watch right now and converted it, you would type a time that looks like 5 1/2 hours earlier than mine. But it's the same time. If you convert it to NSDate, we will both get the exact same NSDate.

So how do you change your NSDate? Quite simple: You don't. NSDate is absolute time, independent of your location on earth.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • I didn't want to change my `NSDate`. I just wanted a `NSDate` object of my current time. Anyway I was able to accomplish it. I added the code as an answer. – Isuru Sep 25 '14 at 13:58
  • 1
    @gnasher729 is correct. You are comparing string representations of `NSDates`, which will (without your choosing to) apply the local time zone. Compare the NSDates directly using date.compare(otherDate). – Grimxn Sep 25 '14 at 14:27
0

Upon further Googling, I came across this post. The method described in it does exactly what I want. The original code is in Objective-C and since my question is in Swift, I'm going to post its Swift translation. \

func toLocalTime() -> NSDate {
    let timeZone = NSTimeZone.localTimeZone()
    let seconds = timeZone.secondsFromGMTForDate(self)

    return NSDate(timeInterval: Double(seconds), sinceDate: self)
}

I added these as extension methods of NSDate so you can simply call them like this.

NSDate.date().toLocalTime()
Isuru
  • 30,617
  • 60
  • 187
  • 303
0

You can compare two dates using any of the following NSDate functions: compare, earlierDate, laterDate, isEqualToDate. You should not compare date strings (oh, goodness, no, think of the nightmare); convert 'date strings' into 'NSDate' as soon as inputed.

In order to compare two dates that arose from strings correctly, you'll need the date strings to be unambiguous. In practice, that requires the date to have a time zone attached. If your server isn't providing a time zone and can't be modified to provide one, then you'll be forced to assume one (which would typically be the time zone where the server is located, assuming one server).

GoZoner
  • 67,920
  • 20
  • 95
  • 145