Nsdate() or Date() Shows the Wrong Time

NSDate() or Date() shows the wrong time

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

Date() shows wrong time

From Apple's documentation:

A Date is independent of a particular calendar or time zone. To
represent a Date to a user, you must interpret it in the context of a
Calendar.

You need the help of Calendar:

let calendar = Calendar(identifier: .gregorian)
let currentDate = Date()
print(calendar.dateComponents(in: calendar.timeZone, from: currentDate))

the output will be:

calendar: gregorian (fixed) timeZone: Europe/Bratislava (current) era: 1 year: 2019 
month: 11 day: 19 hour: 15 minute: 47 second: 14 nanosecond: 285109996 weekday: 3 weekdayOrdinal: 3 quarter: 0 weekOfMonth: 4 weekOfYear: 47 yearForWeekOfYear: 2019 isLeapMonth: false

So you could then access your calendar's components like hour, minute etc.

UPDATE:

@Camile answered in comments to their question using DateFormatter:

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss:Z"
dateFormatter.timeZone = calendar.timeZone
dateFormatter.string(from:currentDate)

will give you

2019-11-19 16:38:03:+0100

iOS NSDate() returns incorrect time

It doesn't return the wrong time. It returns exactly the right time. NSDate doesn't have any timezone information. Right now, my computer and your computer will report the exact same time when we call NSDate ().

NSLog displays NSDate in UTC. That's just what it displays. So if we both call NSLog right now, your computer will log the same date and time as mine. Because it is the same date and time.

If you want to process an NSDate (for example, to display the date and time to a user) you use an NSCalendar. The NSCalendar translates between NSDate, which is the same everywhere in the world, to the values that you want to display in your user interface, which will be different in London or in Kiev. If I look on my watch right now, I will see a different time than you see on your watch, and that is what NSCalendar is there for.

NSDate date method returns wrong result

NSDates are always stored in UTC, actually the dates itselfs dont know anything about timezones or weeks, month, years. They are just a point in time.

To see the correct time for your position on the earth surface, you need to take the NSCalendar, that represents your time model in account. You could use it directly and mess around with your dates, or create a NSDateFormatter that will leave the dates untouched but adjust their appearence to your needs.

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterFullStyle];
[formatter setTimeStyle:NSDateFormatterFullStyle];

NSLog(@"%@", [formatter stringFromDate: date1]);

results in

Thursday, July 12, 2012, 4:36:07 PM Central European Summer Time 

in response to the comment:

try this code as test

NSDate *now = [NSDate date];
NSDate *startOfToday = nil;
NSDate *startOfThisWeek = nil;
NSDate *startOfThisMonth = nil;
NSDate *startOfThisYear = nil;
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&startOfToday interval:NULL forDate:now];
[[NSCalendar currentCalendar] rangeOfUnit:NSWeekCalendarUnit startDate:&startOfThisWeek interval:NULL forDate:now];
[[NSCalendar currentCalendar] rangeOfUnit:NSMonthCalendarUnit startDate:&startOfThisMonth interval:NULL forDate:now];
[[NSCalendar currentCalendar] rangeOfUnit:NSYearCalendarUnit startDate:&startOfThisYear interval:NULL forDate:now];

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterFullStyle];
[formatter setTimeStyle:NSDateFormatterFullStyle];

NSLog(@"%@", now);
NSLog(@"%@", [formatter stringFromDate:now]);

NSLog(@"%@", startOfToday);
NSLog(@"%@", [formatter stringFromDate:startOfToday]);

NSLog(@"%@", startOfThisWeek);
NSLog(@"%@", [formatter stringFromDate:startOfThisWeek]);

NSLog(@"%@", startOfThisMonth);
NSLog(@"%@", [formatter stringFromDate:startOfThisMonth]);

NSLog(@"%@", startOfThisYear);
NSLog(@"%@", [formatter stringFromDate:startOfThisYear]);

you will realize, that the start of the day, week, month and year will be adjusted to your local time, as the first of each NSLog-pair will give you the date in UTC and the second in your local time zone.


on the chat you posted this code

NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; 
[dateFormat setDateFormat:@"yyyy-MM-dd HH:mm"];
[dateFormat setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate *date = [dateFormat dateFromString:dateString];
[dateFormat release];

so the problem is, that the datestring is actually not from GMT, but EET (Eastern European Time)

try

[dateFormat setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"EET"]]; 

but the by far most elegant solution would be to get the datestring with the offset to UTC, similar to 2012-07-12 12:23:00 +0300if some how possible.

In such an case you could parse it with

[dateFormat setDateFormat:@"yyyy-mm-dd HH:mm:ss Z"];
and don't need further time zone handling, as the formatter knows the offset via the Z-specifier.

Also note, that if you don't set any timezone, the device's current should be used. If the user is always in the same timezone as the time from the date string, this should work, too. But if the user leaves that zone, or you inted to have it working world wide, you should use one of the solutions I gave you. With the second (specifying the timezone with-in the datestring) as the preferred one.

Wrong time since.. from timestamp

NSDate().timeIntervalSinceNow return value close to 0.

NSDate() — creates date with current timestamp, you can call it now.
timeIntervalSinceNow here will be difference between time of creating data and method call, miniscule value.

So this:

NSDate().timeIntervalSinceNow-NSDate().timeIntervalSince(date as Date)

Can be seen like this:

0 - now.timeIntervalSince(date as Date)

For all dates in past now.timeIntervalSince(date as Date) is positive, and 0 - positive = negative

And in the end you're subtracting time interval from January 1st, 1970 and get your date of 1969. Btw, why are you doing this?

Also, stop using NSDate in Swift 3, just use Date.

And use this method for timeSincePost calculation.

how I am able to convert it now to like 5 minutes ago etc...

Just use DateFormatter with doesRelativeDateFormatting set to true and get stringFromDate with original date you got with Firebird timestamp.

NSCalendar.dateFromComponents returns wrong time

You can solve your problem by setting the timezone correctly.
For example :

calendar?.timeZone = NSTimeZone(abbreviation: "GMT")!

Getting wrong time from dateformatter

@user30646 -- see if this makes sense. Using your exact function:

func stringToDate(DateString dateString: String) -> NSDate? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyyMMddHHmmss"
dateFormatter.locale = Locale.init(identifier: "en_US_POSIX")
dateFormatter.timeZone = TimeZone(abbreviation: "EST")

if let date = dateFormatter.date(from: dateString) {
return date as NSDate?
}

return nil

}

let dateString = "20150909093700"

let returnedDate = stringToDate(DateString: dateString)

print("Date without formatting or Time Zone: [", returnedDate ?? "return was nil", "]")

let dFormatter = DateFormatter()
dFormatter.timeZone = TimeZone(abbreviation: "EST")
dFormatter.dateStyle = .full
dFormatter.timeStyle = .full

print("Result with formatting and Time Zone: [", dFormatter.string(from: returnedDate as! Date), "]")

You are getting the "correct time" ... you just think you're not because you're looking at the wrong string representation of that date/time.

NSDateFormatter return wrong date + Swift

When you convert from string to NSDate, if you do not set the timezone to the formatter, you will get the NSDate of a date in your local time zone. I suppose that your time zone is GMT+3 .

Then, when you show the value of 'date' (using println, NSLog but not NSDateFormatter), without setting the time zone, you will get GMT+0 time. That why you got 3h later.

Depend on how to use NSDateFormatter, you will have the date string as you want. In your case, It returns what you want, doesn't it?

Remember that NSDate presents a moment of time.

let dateString = "2016-04-02"
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
println("dateString: \(dateString)")

formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
let date = formatter.dateFromString(dateString) //without specify timezone, your dateString "2016-04-02" is your local time (GMT-3),
//means it's 2016-04-02 00:00:000 at GMT+0. That is the value that NSDate holds.

println("date: \(date)") //that why it show 2016-04-01 21:00:000, but not 2016-04-02 00:00:000

formatter.dateFormat = "yyyy-MM-dd"
let formattedDateString = formatter.stringFromDate(date!)
println("formattedDateString: \(formattedDateString)")


Related Topics



Leave a reply



Submit