Get UTC time and local time from NSDate object
Solution 1
The documentation says that the date
method returns a new date set to the current date and time regardless of the language used.
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.
Swift
print(NSDate())
Output: 2014-07-23 17:56:45 +0000
Objective-C
NSLog(@"%@", [NSDate date]);
Output: 2014-07-23 17:58:15 +0000
Result - No difference.
Solution 2
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.
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)
.
Solution 3
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:
Solution 4
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]);
Solution 5
let date = Date()
print(date) // printed date is UTC
If you are using playground, use a print statement to check the time. Playground shows local time until you print it. Do not depend on the right side panel of playground.
This code gives date in UTC. If you need the local time, you should call the following extension with timezone as 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
Comments
-
p0lAris about 4 years
In objective-c, the following code results in the UTC date time information using the
date
API.NSDate *currentUTCDate = [NSDate date]
In Swift however,
let date = NSDate.date()
results in local date and time.
I have two questions:
- How can I get UTC time and local time (well
date
gives local time) inNSDate
objects. - How can I get precision for seconds from the
NSDate
object.
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. - How can I get UTC time and local time (well
-
Hot Licks almost 10 yearsOne 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. -
zaph almost 10 yearsActually the time is based on GMT.
-
p0lAris almost 10 yearsThanks 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()
. -
zaph almost 10 yearsActually 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.
-
p0lAris almost 10 yearsThanks. 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. -
Steven Fisher almost 10 years
dateA.compare(dateB);
-
Steven Fisher almost 10 yearsComparing 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 almost 10 yearsNot 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.
-
Daij-Djan almost 10 yearsit 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
-
p0lAris almost 10 years@StevenFisher I think I have clearly mentioned this - comparing NSDate objects is easy. I just don't want to deal with NSFormatter or other stuff. So if I can package both utc datetime and local datetime in NSDate objects, it will be easier for me. Please re-read the main question.
-
p0lAris almost 10 yearsReiterating: I just want two date objects - one that is responsible for utc time, one for local time (however possible). I understand NSDate but I just don't care about that. I simply want two of these dates packaged as NSDate objects rather than strings or NSFormatter/NSDateFormatter.
-
zaph almost 10 yearsWhere did you get information "GMT, some DaylightSavings time is connected". Perhaps you are thinking of BST?
-
zaph almost 10 yearsFrom 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.
-
Daij-Djan almost 10 yearsyes that wrong of me and I did remember it wrongly but GMT is not UTC and the date has no timezone ;)
-
Daij-Djan almost 10 yearsUTC is MOSTLY the same as GMT - as I remember it!
-
Steven Fisher almost 10 yearsAgain: There's no such thing as a local or UTC
NSDate
. Compare the twoNSDate
; it will do what you want. I suggest reading this again, because it sounds like you're still missing the point. :) -
Hot Licks almost 10 yearsYou can, of course, put any date/time you want in an NSDate object. It can represent Martian time if you wish. But then you're responsible for keeping track of what it means and being very careful to never use it in a way where the "normal" meaning will be assumed.
-
skymook over 9 yearsYes, not a bug. The
description
of theNSDate
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 show2014-07-23 16:56:45 +0000
(GMT or UTC) in the log after I created it. In reality, this is2014-07-23 17:56:45 +0000
(my local timezone). Just imagine they are stored in GTM or UTC and change depending on your timezone. -
Daij-Djan about 9 yearsThat string is what YOU get. By chance :) no formatter and The Output is based on The Locale of The debugger.
-
Ali about 9 yearsIt'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.
-
Daij-Djan about 9 yearsyour 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
-
Steven Fisher almost 9 yearsThis in no way answers the question (or, for that matter, shows the fundamental assumptions behind the question are invalid).
-
Jake T. almost 7 years@skymook if the UTC date is
2014-07-23 16:56:45 +0000
, the local date is actually2014-07-23 17:56:45 +0100
, the+0100
represents the offset from the UTC time. -
abhimuralidharan almost 7 yearsThis will give the current timeZone date.Not UTC.
-
mfaani almost 7 yearsis there anyway to ditch the
+0000
and still keep the seconds? -
Steven Fisher almost 7 yearsJust format it how you like. You shouldn't be relying on the date's description anyway.
-
C0D3 about 4 yearsI don't think this answer answers the question asked here. The question asked is how to get a UTC date in iOS and how to get precision seconds from a Date() object.