Get UTC time and local time from NSDate object
Get UTC time and local time from NSDate object
In objective-c, the following code results in the UTC date time information using the date
API.
date
NSDate *currentUTCDate = [NSDate date]
In Swift however,
let date = NSDate.date()
results in local date and time.
I have two questions:
date
NSDate
NSDate
EDIT 1: Thanks for all the inputs but I am not looking for NSDateFormatter
objects or string values. I am simply looking for NSDate objects (however we cook them up but that's the requirement).
See point 1.
NSDateFormatter
NSDate
A
NSDate
is a moment in time. There is no such thing as a UTC date or a local date. Its just a question of how you display it.– carloabelli
Jul 23 '14 at 17:59
NSDate
NSDate instances are based on the time interval since the first instant of 1 January 2001, GMT. Thus the time zone that a date is created in does not make any difference and does not affect the
NSDate
value.– zaph
Jul 23 '14 at 18:12
NSDate
From the Apple Docs: "The sole primitive method of NSDate, timeIntervalSinceReferenceDate, provides the basis for all the other methods in the NSDate interface. This method returns a time value relative to an absolute reference date—the first instant of 1 January 2001, GMT."
– zaph
Jul 23 '14 at 18:22
9 Answers
9
The documentation says that the date
method returns a new date set to the current date and time regardless of the language used.
date
The issue probably sits somewhere where you present the date using NSDateFormatter
. NSDate
is just a point on a time line. There is no time zones when talking about NSDate
. I made a test.
NSDateFormatter
NSDate
NSDate
print(NSDate())
Output: 2014-07-23 17:56:45 +0000
2014-07-23 17:56:45 +0000
NSLog(@"%@", [NSDate date]);
Output: 2014-07-23 17:58:15 +0000
2014-07-23 17:58:15 +0000
Result - No difference.
Thanks for that. Apparently, playground shows me local time for some reason. Maybe it's just a bug (IDK). I am simply querying
let x = NSDate.date()
.– p0lAris
Jul 23 '14 at 18:17
let x = NSDate.date()
Not a bug; just the way it is. You haven't specified the time zone or format, so you get whatever. My guess is that it's current time zone, US medium date format, and US short time format.
– Steven Fisher
Jul 23 '14 at 18:34
Yes, not a bug. The
description
of the NSDate
object will show local time zone on your current device in the log, but all dates are GMT or UTC in reality. You settings will then show the log of the date set to the timezone you are in. Which is correct. If I was not at GMT lets say (GMT +1 hour), then the date would show 2014-07-23 16:56:45 +0000
(GMT or UTC) in the log after I created it. In reality, this is 2014-07-23 17:56:45 +0000
(my local timezone). Just imagine they are stored in GTM or UTC and change depending on your timezone.– skymook
Jan 6 '15 at 12:11
description
NSDate
2014-07-23 16:56:45 +0000
2014-07-23 17:56:45 +0000
@skymook if the UTC date is
2014-07-23 16:56:45 +0000
, the local date is actually 2014-07-23 17:56:45 +0100
, the +0100
represents the offset from the UTC time.– Jake T.
Jun 15 '17 at 18:42
2014-07-23 16:56:45 +0000
2014-07-23 17:56:45 +0100
+0100
NSDate
is a specific point in time without a time zone. Think of it as the number of seconds that have passed since a reference date. How many seconds have passed in one time zone vs. another since a particular reference date? The answer is the same.
NSDate
Depending on how you output that date (including looking at the debugger), you may get an answer in a different time zone.
If they ran at the same moment, the values of these are the same. They're both the number of seconds since the reference date, which may be formatted on output to UTC or local time. Within the date variable, they're both UTC.
Objective-C:
NSDate *UTCDate = [NSDate date]
Swift:
let UTCDate = NSDate.date()
To explain this, we can use a NSDateFormatter in a playground:
import UIKit
let date = NSDate.date()
// "Jul 23, 2014, 11:01 AM" <-- looks local without seconds. But:
var formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
let defaultTimeZoneStr = formatter.stringFromDate(date)
// "2014-07-23 11:01:35 -0700" <-- same date, local, but with seconds
formatter.timeZone = NSTimeZone(abbreviation: "UTC")
let utcTimeZoneStr = formatter.stringFromDate(date)
// "2014-07-23 18:01:41 +0000" <-- same date, now in UTC
The date output varies, but the date is constant. This is exactly what you're saying. There's no such thing as a local NSDate.
As for how to get microseconds out, you can use this (put it at the bottom of the same playground):
let seconds = date.timeIntervalSince1970
let microseconds = Int(seconds * 1000) % 1000 // chops off seconds
To compare two dates, you can use date.compare(otherDate)
.
date.compare(otherDate)
One thing to note is that if you examine a date value using the debugger it's apt to be shown in local time, while if you use
po
to display it while debugging (or simply use NSLog) it will always be shown in UTC.– Hot Licks
Jul 23 '14 at 18:11
po
Actually the time is based on GMT.
– zaph
Jul 23 '14 at 18:16
Thanks. Also, as I mentioned, I want to compare dates, etc. So I want to have these two time values typed using the
NSDate
type. Is there a way to do that. NSFormatter
doesn't solve any purpose.– p0lAris
Jul 23 '14 at 18:18
NSDate
NSFormatter
dateA.compare(dateB);
– Steven Fisher
Jul 23 '14 at 18:22
dateA.compare(dateB);
Comparing dates is easy, I've added that. But as your question was regarding the different date you saw, explaining why you saw different dates was important. And NSDateFormatter is the best way to do that. :)
– Steven Fisher
Jul 23 '14 at 18:24
Xcode 9 • Swift 4 (also works Swift 3.x)
extension Formatter
// create static date formatters for your date representations
static let preciseLocalTime: DateFormatter =
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "HH:mm:ss.SSS"
return formatter
()
static let preciseGMTTime: DateFormatter =
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "HH:mm:ss.SSS"
return formatter
()
extension Date
// you can create a read-only computed property to return just the nanoseconds from your date time
var nanosecond: Int return Calendar.current.component(.nanosecond, from: self)
// the same for your local time
var preciseLocalTime: String
return Formatter.preciseLocalTime.string(for: self) ?? ""
// or GMT time
var preciseGMTTime: String
return Formatter.preciseGMTTime.string(for: self) ?? ""
Playground testing
Date().preciseLocalTime // "09:13:17.385" GMT-3
Date().preciseGMTTime // "12:13:17.386" GMT
Date().nanosecond // 386268973
This might help you also formatting your dates:
a date is independant of any timezone, so use a Dateformatter and attach a timezone for display:
swift:
let date = NSDate()
let dateFormatter = NSDateFormatter()
let timeZone = NSTimeZone(name: "UTC")
dateFormatter.timeZone = timeZone
println(dateFormatter.stringFromDate(date))
objC:
NSDate *date = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeZone:timeZone];
NSLog(@"%@", [dateFormatter stringFromDate:date]);
Actually the date is based on GMT. If it was not based on a specific time zone it could not be displayed as another time zone.
– zaph
Jul 23 '14 at 18:17
it is not GMT based I am afraid. If anything you can call it UTC based but for me UTC = zulu time = no timezone. In short the difference UTC vs .GMT is that with GMT, some DaylightSavings time is connected
– Daij-Djan
Jul 23 '14 at 18:34
NSDate basically wraps a unix timestamp
– Daij-Djan
Jul 23 '14 at 18:34
Where did you get information "GMT, some DaylightSavings time is connected". Perhaps you are thinking of BST?
– zaph
Jul 23 '14 at 19:00
From the Apple docs: "the first instant of 1 January 2001, GMT." That is not a unix timestamp which has an epoch of 1 January 1970. UTC did replace GMT and for most purposes, UTC is used interchangeably with GMT.
– zaph
Jul 23 '14 at 19:03
Xcode 9 • Swift 4 or Swift 3:
let date = Date() // default is UTC.
This code gives date in UTC. If you need the local time, you should call the following extension with timezone as Timezone.current
Timezone.current
extension Date
var currentUTCTimeZoneDate: String
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier: "UTC")
formatter.amSymbol = "AM"
formatter.pmSymbol = "PM"
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
return formatter.string(from: self)
For UTC time, use it like: Date().currentUTCTimeZoneDate
Date().currentUTCTimeZoneDate
At the moment (with the latest changes to Swift), NSDate.date()
is not longer available.
NSDate.date()
Instead you just need to initialize NSDate
and it gets the current date and time.
To try it, in a playground:
NSDate
var d = NSDate()
d
and you will get:
Oct 22, 2014, 12:20 PM"
That string is what YOU get. By chance :) no formatter and The Output is based on The Locale of The debugger.
– Daij-Djan
Mar 25 '15 at 6:11
It's not about the string , it's about getting current date time , and by just instantiating the NSDate as I said YOU will get the current datetime too.
– Ali
Mar 25 '15 at 9:36
your string is your local time and that what ticket is about is: "in objective-c, the following code [X} results in the UTC date time information, in swift it results in local date and time. X" ==> the debuggers date formatter
– Daij-Djan
Mar 25 '15 at 9:38
This in no way answers the question (or, for that matter, shows the fundamental assumptions behind the question are invalid).
– Steven Fisher
Jul 23 '15 at 16:20
Swift 3
You can get Date based on your current timezone from UTC
extension Date
func currentTimeZoneDate() -> String
let dtf = DateFormatter()
dtf.timeZone = TimeZone.current
dtf.dateFormat = "yyyy-MM-dd HH:mm:ss"
return dtf.string(from: self)
Call like this:
Date().currentTimeZoneDate()
This will give the current timeZone date.Not UTC.
– abhi1992
Jun 22 '17 at 6:56
My Xcode Version 6.1.1 (6A2008a)
In playground, test like this:
// I'm in East Timezone 8
let x = NSDate() //Output:"Dec 29, 2014, 11:37 AM"
let y = NSDate.init() //Output:"Dec 29, 2014, 11:37 AM"
println(x) //Output:"2014-12-29 03:37:24 +0000"
// seconds since 2001
x.hash //Output:441,517,044
x.hashValue //Output:441,517,044
x.timeIntervalSinceReferenceDate //Output:441,517,044.875367
// seconds since 1970
x.timeIntervalSince1970 //Output:1,419,824,244.87537
I found an easier way to get UTC in Swift4. Put this code in playground
let date = Date()
//"Mar 15, 2018 at 4:01 PM"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
let newDate = dateFormatter.string(from: date)
//"2018-03-15 21:05:04 +0000"
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
NSDate
gives sub-second precision.– Stonz2
Jul 23 '14 at 17:54