NSDate() or Date() shows the wrong time - swift

When I try to log the current date:
print(NSDate())
or
print(Date())
(in Swift 3)
Or any date object, it shows the wrong time. For example, it's about 16:12 now, but the above displayed
2016-10-08 20:11:40 +0000
Is my date in the wrong time zone? How do I fix my date to have the correct time zone?
Why is that, and how to I fix it? How do I easily display an arbitrary date in my local time zone, either in print statements or in the debugger?
(Note that this question is a "ringer" so that I can provide a simple Swift 3/Swift 2 Date/NSDate extension that lets you easily display any date object in your local time zone.

NSDate (or Date in Swift ≥ V3) does not have a time zone. It records an instant in time all over the world.
Internally, date objects record the number of seconds since the "epoch date", or Midnight on January 1, 2001 in Greenwich Mean Time, a.k.a UTC.
We normally think of dates in our local time zone.
If you log a date using
print(NSDate())
The system displays the current date, but it expresses it in UTC/Greenwich Mean Time. So the only place the time will look correct is in that time zone.
You get the same issue in the debugger if you issue the debugger command
e NSDate()
This is a pain. I personally wish iOS/Mac OS would display dates using the user's current time zone, but they don't.
EDIT #2:
An improvement on my previous use of localized string that makes it a little easier to use is to create an extension to the Date class:
extension Date {
func localString(dateStyle: DateFormatter.Style = .medium, timeStyle: DateFormatter.Style = .medium) -> String {
return DateFormatter.localizedString(from: self, dateStyle: dateStyle, timeStyle: timeStyle)
}
}
That way you can just use an expression like Date().localString(), or if you want to only print the time, you can use Date().localString(dateStyle:.none)
EDIT:
I just discovered that NSDateFormatter (DateFormatter in Swift 3) has a class method localizedString. That does what my extension below does, but more simply and cleanly. Here is the declaration:
class func localizedString(from date: Date, dateStyle dstyle: DateFormatter.Style, timeStyle tstyle: DateFormatter.Style) -> String
So you'd simply use
let now = Date()
print (DateFormatter.localizedString(
from: now,
dateStyle: .short,
timeStyle: .short))
You can pretty much ignore everything below.
I have created a category of the NSDate class (Date in swift 3) that has a method localDateString that displays a date in the user's local time zone.
Here is the category in Swift 3 form: (filename Date_displayString.swift)
extension Date {
#nonobjc static var localFormatter: DateFormatter = {
let dateStringFormatter = DateFormatter()
dateStringFormatter.dateStyle = .medium
dateStringFormatter.timeStyle = .medium
return dateStringFormatter
}()
func localDateString() -> String
{
return Date.localFormatter.string(from: self)
}
}
And in Swift 2 form:
extension NSDate {
#nonobjc static var localFormatter: NSDateFormatter = {
let dateStringFormatter = NSDateFormatter()
dateStringFormatter.dateStyle = .MediumStyle
dateStringFormatter.timeStyle = .MediumStyle
return dateStringFormatter
}()
public func localDateString() -> String
{
return NSDate.localFormatter.stringFromDate(self)
}
}
(If you prefer a different date format it's pretty easy to modify the format used by the date formatters. It's also straightforward to display the date and time in any timezone you need.)
I would suggest putting the appropriate Swift 2/Swift 3 version of this file in all of your projects.
You can then use
Swift 2:
print(NSDate().localDateString())
Swift 3:
print(Date().localDateString())

A simple way to correct the Date for your timezone would be to use TimeZone.current.secondsFromGMT()
Something like this for a local timestamp value for example:
let currentLocalTimestamp = (Int(Date().timeIntervalSince1970) + TimeZone.current.secondsFromGMT())

Related

Swift String to Date conversion returning wrong time [duplicate]

When I try to log the current date:
print(NSDate())
or
print(Date())
(in Swift 3)
Or any date object, it shows the wrong time. For example, it's about 16:12 now, but the above displayed
2016-10-08 20:11:40 +0000
Is my date in the wrong time zone? How do I fix my date to have the correct time zone?
Why is that, and how to I fix it? How do I easily display an arbitrary date in my local time zone, either in print statements or in the debugger?
(Note that this question is a "ringer" so that I can provide a simple Swift 3/Swift 2 Date/NSDate extension that lets you easily display any date object in your local time zone.
NSDate (or Date in Swift ≥ V3) does not have a time zone. It records an instant in time all over the world.
Internally, date objects record the number of seconds since the "epoch date", or Midnight on January 1, 2001 in Greenwich Mean Time, a.k.a UTC.
We normally think of dates in our local time zone.
If you log a date using
print(NSDate())
The system displays the current date, but it expresses it in UTC/Greenwich Mean Time. So the only place the time will look correct is in that time zone.
You get the same issue in the debugger if you issue the debugger command
e NSDate()
This is a pain. I personally wish iOS/Mac OS would display dates using the user's current time zone, but they don't.
EDIT #2:
An improvement on my previous use of localized string that makes it a little easier to use is to create an extension to the Date class:
extension Date {
func localString(dateStyle: DateFormatter.Style = .medium, timeStyle: DateFormatter.Style = .medium) -> String {
return DateFormatter.localizedString(from: self, dateStyle: dateStyle, timeStyle: timeStyle)
}
}
That way you can just use an expression like Date().localString(), or if you want to only print the time, you can use Date().localString(dateStyle:.none)
EDIT:
I just discovered that NSDateFormatter (DateFormatter in Swift 3) has a class method localizedString. That does what my extension below does, but more simply and cleanly. Here is the declaration:
class func localizedString(from date: Date, dateStyle dstyle: DateFormatter.Style, timeStyle tstyle: DateFormatter.Style) -> String
So you'd simply use
let now = Date()
print (DateFormatter.localizedString(
from: now,
dateStyle: .short,
timeStyle: .short))
You can pretty much ignore everything below.
I have created a category of the NSDate class (Date in swift 3) that has a method localDateString that displays a date in the user's local time zone.
Here is the category in Swift 3 form: (filename Date_displayString.swift)
extension Date {
#nonobjc static var localFormatter: DateFormatter = {
let dateStringFormatter = DateFormatter()
dateStringFormatter.dateStyle = .medium
dateStringFormatter.timeStyle = .medium
return dateStringFormatter
}()
func localDateString() -> String
{
return Date.localFormatter.string(from: self)
}
}
And in Swift 2 form:
extension NSDate {
#nonobjc static var localFormatter: NSDateFormatter = {
let dateStringFormatter = NSDateFormatter()
dateStringFormatter.dateStyle = .MediumStyle
dateStringFormatter.timeStyle = .MediumStyle
return dateStringFormatter
}()
public func localDateString() -> String
{
return NSDate.localFormatter.stringFromDate(self)
}
}
(If you prefer a different date format it's pretty easy to modify the format used by the date formatters. It's also straightforward to display the date and time in any timezone you need.)
I would suggest putting the appropriate Swift 2/Swift 3 version of this file in all of your projects.
You can then use
Swift 2:
print(NSDate().localDateString())
Swift 3:
print(Date().localDateString())
A simple way to correct the Date for your timezone would be to use TimeZone.current.secondsFromGMT()
Something like this for a local timestamp value for example:
let currentLocalTimestamp = (Int(Date().timeIntervalSince1970) + TimeZone.current.secondsFromGMT())

Truncating time off a date retains some time component [duplicate]

When I try to log the current date:
print(NSDate())
or
print(Date())
(in Swift 3)
Or any date object, it shows the wrong time. For example, it's about 16:12 now, but the above displayed
2016-10-08 20:11:40 +0000
Is my date in the wrong time zone? How do I fix my date to have the correct time zone?
Why is that, and how to I fix it? How do I easily display an arbitrary date in my local time zone, either in print statements or in the debugger?
(Note that this question is a "ringer" so that I can provide a simple Swift 3/Swift 2 Date/NSDate extension that lets you easily display any date object in your local time zone.
NSDate (or Date in Swift ≥ V3) does not have a time zone. It records an instant in time all over the world.
Internally, date objects record the number of seconds since the "epoch date", or Midnight on January 1, 2001 in Greenwich Mean Time, a.k.a UTC.
We normally think of dates in our local time zone.
If you log a date using
print(NSDate())
The system displays the current date, but it expresses it in UTC/Greenwich Mean Time. So the only place the time will look correct is in that time zone.
You get the same issue in the debugger if you issue the debugger command
e NSDate()
This is a pain. I personally wish iOS/Mac OS would display dates using the user's current time zone, but they don't.
EDIT #2:
An improvement on my previous use of localized string that makes it a little easier to use is to create an extension to the Date class:
extension Date {
func localString(dateStyle: DateFormatter.Style = .medium, timeStyle: DateFormatter.Style = .medium) -> String {
return DateFormatter.localizedString(from: self, dateStyle: dateStyle, timeStyle: timeStyle)
}
}
That way you can just use an expression like Date().localString(), or if you want to only print the time, you can use Date().localString(dateStyle:.none)
EDIT:
I just discovered that NSDateFormatter (DateFormatter in Swift 3) has a class method localizedString. That does what my extension below does, but more simply and cleanly. Here is the declaration:
class func localizedString(from date: Date, dateStyle dstyle: DateFormatter.Style, timeStyle tstyle: DateFormatter.Style) -> String
So you'd simply use
let now = Date()
print (DateFormatter.localizedString(
from: now,
dateStyle: .short,
timeStyle: .short))
You can pretty much ignore everything below.
I have created a category of the NSDate class (Date in swift 3) that has a method localDateString that displays a date in the user's local time zone.
Here is the category in Swift 3 form: (filename Date_displayString.swift)
extension Date {
#nonobjc static var localFormatter: DateFormatter = {
let dateStringFormatter = DateFormatter()
dateStringFormatter.dateStyle = .medium
dateStringFormatter.timeStyle = .medium
return dateStringFormatter
}()
func localDateString() -> String
{
return Date.localFormatter.string(from: self)
}
}
And in Swift 2 form:
extension NSDate {
#nonobjc static var localFormatter: NSDateFormatter = {
let dateStringFormatter = NSDateFormatter()
dateStringFormatter.dateStyle = .MediumStyle
dateStringFormatter.timeStyle = .MediumStyle
return dateStringFormatter
}()
public func localDateString() -> String
{
return NSDate.localFormatter.stringFromDate(self)
}
}
(If you prefer a different date format it's pretty easy to modify the format used by the date formatters. It's also straightforward to display the date and time in any timezone you need.)
I would suggest putting the appropriate Swift 2/Swift 3 version of this file in all of your projects.
You can then use
Swift 2:
print(NSDate().localDateString())
Swift 3:
print(Date().localDateString())
A simple way to correct the Date for your timezone would be to use TimeZone.current.secondsFromGMT()
Something like this for a local timestamp value for example:
let currentLocalTimestamp = (Int(Date().timeIntervalSince1970) + TimeZone.current.secondsFromGMT())

Swift date format [duplicate]

When I try to log the current date:
print(NSDate())
or
print(Date())
(in Swift 3)
Or any date object, it shows the wrong time. For example, it's about 16:12 now, but the above displayed
2016-10-08 20:11:40 +0000
Is my date in the wrong time zone? How do I fix my date to have the correct time zone?
Why is that, and how to I fix it? How do I easily display an arbitrary date in my local time zone, either in print statements or in the debugger?
(Note that this question is a "ringer" so that I can provide a simple Swift 3/Swift 2 Date/NSDate extension that lets you easily display any date object in your local time zone.
NSDate (or Date in Swift ≥ V3) does not have a time zone. It records an instant in time all over the world.
Internally, date objects record the number of seconds since the "epoch date", or Midnight on January 1, 2001 in Greenwich Mean Time, a.k.a UTC.
We normally think of dates in our local time zone.
If you log a date using
print(NSDate())
The system displays the current date, but it expresses it in UTC/Greenwich Mean Time. So the only place the time will look correct is in that time zone.
You get the same issue in the debugger if you issue the debugger command
e NSDate()
This is a pain. I personally wish iOS/Mac OS would display dates using the user's current time zone, but they don't.
EDIT #2:
An improvement on my previous use of localized string that makes it a little easier to use is to create an extension to the Date class:
extension Date {
func localString(dateStyle: DateFormatter.Style = .medium, timeStyle: DateFormatter.Style = .medium) -> String {
return DateFormatter.localizedString(from: self, dateStyle: dateStyle, timeStyle: timeStyle)
}
}
That way you can just use an expression like Date().localString(), or if you want to only print the time, you can use Date().localString(dateStyle:.none)
EDIT:
I just discovered that NSDateFormatter (DateFormatter in Swift 3) has a class method localizedString. That does what my extension below does, but more simply and cleanly. Here is the declaration:
class func localizedString(from date: Date, dateStyle dstyle: DateFormatter.Style, timeStyle tstyle: DateFormatter.Style) -> String
So you'd simply use
let now = Date()
print (DateFormatter.localizedString(
from: now,
dateStyle: .short,
timeStyle: .short))
You can pretty much ignore everything below.
I have created a category of the NSDate class (Date in swift 3) that has a method localDateString that displays a date in the user's local time zone.
Here is the category in Swift 3 form: (filename Date_displayString.swift)
extension Date {
#nonobjc static var localFormatter: DateFormatter = {
let dateStringFormatter = DateFormatter()
dateStringFormatter.dateStyle = .medium
dateStringFormatter.timeStyle = .medium
return dateStringFormatter
}()
func localDateString() -> String
{
return Date.localFormatter.string(from: self)
}
}
And in Swift 2 form:
extension NSDate {
#nonobjc static var localFormatter: NSDateFormatter = {
let dateStringFormatter = NSDateFormatter()
dateStringFormatter.dateStyle = .MediumStyle
dateStringFormatter.timeStyle = .MediumStyle
return dateStringFormatter
}()
public func localDateString() -> String
{
return NSDate.localFormatter.stringFromDate(self)
}
}
(If you prefer a different date format it's pretty easy to modify the format used by the date formatters. It's also straightforward to display the date and time in any timezone you need.)
I would suggest putting the appropriate Swift 2/Swift 3 version of this file in all of your projects.
You can then use
Swift 2:
print(NSDate().localDateString())
Swift 3:
print(Date().localDateString())
A simple way to correct the Date for your timezone would be to use TimeZone.current.secondsFromGMT()
Something like this for a local timestamp value for example:
let currentLocalTimestamp = (Int(Date().timeIntervalSince1970) + TimeZone.current.secondsFromGMT())

Print of Date() displays time minus 1 hour [duplicate]

When I try to log the current date:
print(NSDate())
or
print(Date())
(in Swift 3)
Or any date object, it shows the wrong time. For example, it's about 16:12 now, but the above displayed
2016-10-08 20:11:40 +0000
Is my date in the wrong time zone? How do I fix my date to have the correct time zone?
Why is that, and how to I fix it? How do I easily display an arbitrary date in my local time zone, either in print statements or in the debugger?
(Note that this question is a "ringer" so that I can provide a simple Swift 3/Swift 2 Date/NSDate extension that lets you easily display any date object in your local time zone.
NSDate (or Date in Swift ≥ V3) does not have a time zone. It records an instant in time all over the world.
Internally, date objects record the number of seconds since the "epoch date", or Midnight on January 1, 2001 in Greenwich Mean Time, a.k.a UTC.
We normally think of dates in our local time zone.
If you log a date using
print(NSDate())
The system displays the current date, but it expresses it in UTC/Greenwich Mean Time. So the only place the time will look correct is in that time zone.
You get the same issue in the debugger if you issue the debugger command
e NSDate()
This is a pain. I personally wish iOS/Mac OS would display dates using the user's current time zone, but they don't.
EDIT #2:
An improvement on my previous use of localized string that makes it a little easier to use is to create an extension to the Date class:
extension Date {
func localString(dateStyle: DateFormatter.Style = .medium, timeStyle: DateFormatter.Style = .medium) -> String {
return DateFormatter.localizedString(from: self, dateStyle: dateStyle, timeStyle: timeStyle)
}
}
That way you can just use an expression like Date().localString(), or if you want to only print the time, you can use Date().localString(dateStyle:.none)
EDIT:
I just discovered that NSDateFormatter (DateFormatter in Swift 3) has a class method localizedString. That does what my extension below does, but more simply and cleanly. Here is the declaration:
class func localizedString(from date: Date, dateStyle dstyle: DateFormatter.Style, timeStyle tstyle: DateFormatter.Style) -> String
So you'd simply use
let now = Date()
print (DateFormatter.localizedString(
from: now,
dateStyle: .short,
timeStyle: .short))
You can pretty much ignore everything below.
I have created a category of the NSDate class (Date in swift 3) that has a method localDateString that displays a date in the user's local time zone.
Here is the category in Swift 3 form: (filename Date_displayString.swift)
extension Date {
#nonobjc static var localFormatter: DateFormatter = {
let dateStringFormatter = DateFormatter()
dateStringFormatter.dateStyle = .medium
dateStringFormatter.timeStyle = .medium
return dateStringFormatter
}()
func localDateString() -> String
{
return Date.localFormatter.string(from: self)
}
}
And in Swift 2 form:
extension NSDate {
#nonobjc static var localFormatter: NSDateFormatter = {
let dateStringFormatter = NSDateFormatter()
dateStringFormatter.dateStyle = .MediumStyle
dateStringFormatter.timeStyle = .MediumStyle
return dateStringFormatter
}()
public func localDateString() -> String
{
return NSDate.localFormatter.stringFromDate(self)
}
}
(If you prefer a different date format it's pretty easy to modify the format used by the date formatters. It's also straightforward to display the date and time in any timezone you need.)
I would suggest putting the appropriate Swift 2/Swift 3 version of this file in all of your projects.
You can then use
Swift 2:
print(NSDate().localDateString())
Swift 3:
print(Date().localDateString())
A simple way to correct the Date for your timezone would be to use TimeZone.current.secondsFromGMT()
Something like this for a local timestamp value for example:
let currentLocalTimestamp = (Int(Date().timeIntervalSince1970) + TimeZone.current.secondsFromGMT())

Swift 4.1 couldn't not convert String to local Date, always return UTC Date

I want to transfer a date string to Date.
let a = DateFormatter()
a.dateFormat = "yyyy-MM-dd HH:mm:ss"
guard let datea = a.date(from: "2018-06-21 00:00:00") else {
fatalError("ERROR: Date conversion failed due to mismatched format.")
}
print("ans", datea)
But it always print "ans 2018-06-20 16:00:00 +0000"
Why it could not print the original string date "2018-06-21 00:00:00"?
What wrong with my code ?
A Date is not a string. A Date is a moment in time. It has no clock. It has no time zones. It has no calendar. It is just an instant in time, independent of location or localization.
As a debugging convenience, a Date can be easily converted to a string in a pre-defined format using its .description (which is what print calls). As with all .description methods, you should never use this string for anything but debugging (or possibly logging). There is no promise about what format this string is in.
If you need some specific string representation, then you should use the DateFormatter:
print("ans", a.string(from: datea))
You need to provide timeZone to get the time according to that provided timeZone so to convert UTC time to local time your code should be look like that.
let a = DateFormatter()
a.dateFormat = "yyyy-MM-dd HH:mm:ss"
a.timeZone = TimeZone(abbreviation: "UTC")
let dt = a.date(from: "2018-06-21 00:00:00")
a.timeZone = TimeZone.current
a.dateFormat = "yyyy-MM-dd HH:mm:ss" //change the dateFormat according to your need
let dateString = a.string(from: dt!)
print("now the dateString is \(dateString)")
//printed result (now the dateString is 2018-06-21 05:30:00 )
As Rob Napier says in his answer, a Date object does not have a time zone. It represents a moment in time anywhere on the planet.
If you want to display a Date as a month, day, year, and time, you need to specify a particular time zone.
If you just print a date, like print(Date()), you get the default description property of the date object, which shows the date expressed in UTC. That's probably not what you want.
I defined an extension to Date that lets me see dates expressed in the user's current locale and time zone:
extension Date {
func localString(dateStyle: DateFormatter.Style = .medium, timeStyle: DateFormatter.Style = .medium) -> String {
return DateFormatter.localizedString(from: self, dateStyle: dateStyle, timeStyle: timeStyle)
}
func timeString(timeStyle: DateFormatter.Style = .medium) -> String {
return localString(dateStyle: .none, timeStyle: timeStyle)
}
}
If you add that extension to your project you can use it like this:
print(print("ans", datea.localString())
And you'll see your Date in the device's current time zone. It's very useful for debugging.