2

please help me to get local date and the start of the day, I mean the midnight. For getting local date I'm using code below, but I dont think it is right

var calendar = NSCalendar(calendarIdentifier: NSGregorianCalendar)
        calendar!.timeZone = NSTimeZone.localTimeZone()
        let components = NSDateComponents()
        components.second = NSTimeZone.localTimeZone().secondsFromGMT
        let today = calendar!.dateByAddingComponents(components, toDate: NSDate(), options: nil)

But I can't get the midnight of the day, it keeps returning time 21.00

var comps = calendar!.components(NSCalendarUnit.YearCalendarUnit | .MonthCalendarUnit | .DayCalendarUnit | .HourCalendarUnit | .MinuteCalendarUnit | .SecondCalendarUnit, fromDate: today!)
        comps.hour = 0
        comps.minute = 0
        comps.second = 0

        let startToday = calendar!.dateFromComponents(comps)!

even this return 21.00

calendar!.startOfDayForDate(today)
nzackoya
  • 356
  • 2
  • 8
  • 3
    This looks like another duplicate of "The description of NSDate always uses GMT". See for example http://stackoverflow.com/questions/8466744/getting-date-from-nsdate-date-off-by-a-few-hours. – Martin R Aug 14 '15 at 20:22
  • Note that `startToday` is set to midnight according to your local timezone, and that may be 21:00 in Greenwich. – Martin R Aug 14 '15 at 20:30
  • Local date at the computer location, or local date anywhere? And for the start of the day, what timezone you want the result in? UTC? – MirekE Aug 14 '15 at 20:51

1 Answers1

0

NSDate does not have an attached timezone. For some head-scratching reason, Apple decided to always display the date in GMT when you print it. After enough hair loss on this, I decided to write my own description method see the date in my local time zone:

extension NSDate {
    public var localTimeString : String {
        let formatter = NSDateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
        formatter.timeZone = NSTimeZone.localTimeZone()

        return formatter.stringFromDate(self)
    }
}

let now = NSDate()
let flags : NSCalendarUnit = [.Day, .Month, .Year]
let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let components = gregorian.components(flags, fromDate: now)
let today12AM = gregorian.dateFromComponents(components)!

print(today12AM)
print(today12AM.localTimeString)

Edit:

You can construct a point in time manually:

let x = gregorian.dateWithEra(1, year: 2015, month: 8, day: 15, hour: 0, minute: 0, second: 0, nanosecond: 0)!
print(x)
print(x.localTimeString)

print(x.timeIntervalSince1970) // seconds since midnight Jan 1, 1970
print(today12AM.timeIntervalSince1970)

x is no different than today12AM. As I said, NSDate has no built-in timezone. When you use print, it converts your date into GMT. That's why it appears superficially different from the same point in time when expressed in your own timezone.

Code Different
  • 90,614
  • 16
  • 144
  • 163
  • It returns string representation of the date, but I need the date instance, so today12AM is still 21:00 – nzackoya Aug 15 '15 at 09:34
  • I don't think you are correct that Apple displays the local time in UTC when printing. The documentation for Date states it is independent of calendars, etc. (i.e., it's absolute, e.g. UTC). The documentation for NSDate is substantially clearer, saying that it is an offset from Jan 1, 1970 UTC. So Date is always UTC, which is why Apple displays it as such. – prewett Feb 29 '20 at 07:23