NSDate() or Date() shows the wrong time

后端 未结 2 1936
走了就别回头了
走了就别回头了 2020-11-22 10:51

When I try to log the current date:

print(NSDate())

or

print(Date()) 

(in Swift 3)

Or any date o

相关标签:
2条回答
  • 2020-11-22 11:11

    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())

    0 讨论(0)
  • 2020-11-22 11:30

    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())
    
    0 讨论(0)
提交回复
热议问题