NSDateFromString, parsing a date in the very past - cocoa-touch

I'm executing this code to parse date 01 January 1800:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"ddMMyyyy"];
NSDate *date = [formatter dateFromString:#"01011800"];
when I print date with
NSLog(#"%#", date);
I get
1799-12-31 23:10:04 +0000
My expected result is 1799-12-31 23:00:00 +0000: I'm in central Europe and at 1st January I have a 1.00 hours offset respect to UTC, but I cannot understand where that 10 minutes and 4 seconds come from.

Have a good look on the internet about time zone changes in your area through the last few hundred years. Bets are that the result is actually correct, and that in 1800 your local time zone was off by ten minutes and four seconds.
For a date in 1800, Apple obviously doesn't use what the timezone information is today, but what it was 214 years ago.

Related

NSDate adds 2 hrs [duplicate]

This question already has an answer here:
returns a date an hour in the future
(1 answer)
Closed 8 years ago.
I will appreciate if someone could please advise me what is wrong with the date formatting. I have the following date as string from webservice :
20141211200300 //yyyyMMddHHmmss -->2014/12/11 20:03:00
But when I format it using the following format it adds 2 hrs
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyyMMddHHmmss"];
NSDate *date = [dateFormatter dateFromString:localDate];
The output I get in console is
2014-12-11 10:03:00 +0000
I tried adding GMT timezone as well as Australia/Brisbane still get the same issue.
You did not show the code that printed the number. If you used NSLog() there is probably a time zone issue, Note that the printed time is in GMT. Is your time zone two hours from GMT?

NSDate with no time

I have written the following method:
- (NSDate *)stringToDate:(NSString *)dateString
{
// Convert string to date
NSDateFormatter * dateFormat = [[NSDateFormatter alloc] init];
NSTimeZone *tz = [NSTimeZone timeZoneWithName:#"America/New_York"];
[dateFormat setDateFormat:#"M/d/yyyy HH:mm:ss"];
[dateFormat setTimeZone:tz];
NSDate * date = [dateFormat dateFromString:[NSString stringWithFormat:#"%# 00:00:00", dateString]];
return dateOnly;
}
When I call this with just a date such as 11/1/2013 or 11/13/2013 I get 2013-11-01 04:00:00 +0000 and 2013-11-13 05:00:00 +0000.
If I set a breakpoint on the return the date appears right, but if I break at in the calling function after this call, the date is returned with the time.
How come my time is not always 0. Can anyway tell me what is wrong in my function?
Thank you
UPDATE:
The input string is as follows: 11/1/2013 and 11/13/2013
NSDate is a point in time. It will always have a time component.
And if not printed as a string form a NSDateFormatter, the Date and time will always be the one of UTC/GMT.
The format and the date string must fit.
NSString *dateString = #"11/1/2013";
[dateFormat setDateFormat:#"M/d/yyyy"];
The one hour apart comes from the Daylight saving time. Till November, 3rd 2013 New York has Summer time. http://www.timeanddate.com/worldclock/clockchange.html?n=179
Ok, so can I ignore that? I am trying to compare NSDates when I do my comparison fails because of the time part
You should create dates with with a time during the day — i.e. noon — to be save of DST mess and compare those. Use NSComponents for that.
A must-see for any iOS/Cocoa-Developer: the fantastic WWDC 2011 Video "Session 117 - Performing Calendar Calculations".

Converting NSDate

I have an NSDate (lets call it x), 12 September, 2012 10:18PM (GMT). I want to convert x to a minute before my current time zone's (EST) midnight. So, x represented in EST with NSDateFormatter after conversion would be 12 September, 2012 11:59PM (EST). What's the best way to do this?
Thanks
Take a look at NSDateComponents: https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSDateComponents_Class/Reference/Reference.html
I believe you'll need to convert the NSDate to NSDateComponents, set the time to 11:59PM, then convert back to NSDate.
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [calendar components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit) fromDate:date];
[components setHour:23];
[components setMinute:59];
NSDate *convertedDate = [calendar dateFromComponents:components];
NSLog(#"date=%#, convertedDate=%#", date, convertedDate);
Such manipulations can be easily done with the numeric representation of a date. In this representation, you deal with the number of seconds since a reference date.
The reference date for the purpose of the timeIntervalSinceReferenceDate is January 1st, 2001, at 00:00:00 GMT.
NSDate* date = [NSDate date];
NSInteger secondsSinceReferenceDate = [date timeIntervalSinceReferenceDate];
secondsSinceReferenceDate += 86400 - (secondsSinceReferenceDate % 86400);
secondsSinceReferenceDate -= 60;
secondsSinceReferenceDate -= [NSTimeZone.localTimeZone secondsFromGMTForDate:date];
NSDate* justBeforeToday =
[NSDate dateWithTimeIntervalSinceReferenceDate:secondsSinceReferenceDate];
NSLog(#"Date used was %#", date);
NSLog(#"Just before tomorrow is %#", justBeforeToday);
Since there are 86400 seconds in a day (24 hours times 60 minutes 60 times 60 seconds = 86400 seconds), you know that 86400 - (secondsSinceReferenceDate % 86400) is the number of seconds there are still to midnight. So if you take today's date (or any other valid date), add this number of seconds, and then subtract another 60 seconds, you'll have today's evening at 11:59 PM in the GMT timezone.
With [NSTimeZone.localTimeZone secondsFromGMTForDate:], you know how many seconds your timezone is offset from the GMT timezone. By subtracting this offset to your integer representation, you effectively get when it will be 11:59 PM in your local timezone.
Here's a sample output:
Date used was 2012-09-12 22:37:49 +0000
Just before tomorrow is 2012-09-13 03:59:00 +0000
I'm in the EDT timezone too, and this looks like the correct answer (remember Standard Time is -5 from GMT, but right now we're in daylight savings, so it's -4 from GMT, which is invariant).

why conversion of double to string using NSDate adds extra 30 min

double duration = 20; // duration is in seconds
NSDate* durationDate = [[NSDate alloc]initWithTimeIntervalSinceReferenceDate:duration];
NSDateFormatter *formatter = nil;
formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:#"mm:ss"];
NSString *durationString=[formatter stringFromDate:durationDate];//here durationString should have 20
but i am getting 30:20? from where this 30 min is getting added. I have tried giving bigger numbers then also same result
please let me know thoughts on this and how to solve this
You're probably on India Standard Time?
The reference date is defined to be at midnight GMT. IST is GMT+5:30.
So when you add 20 seconds to the reference date you get 20 seconds past midnight in GMT. When you then create a date formatter and don't set anything else to it, it'll operate in your device's natural time zone. That means that when you ask it for the minutes and seconds at the end of the time you get 30 minutes and 20 seconds.
NSDates are an absolute time, abstract of any time zone or calendar. If five devices in five separate time zones all call [NSDate date] simultaneously to get the current time, they'd all get objects with the same value.
NSDateFormatter combines an NSDate with an NSCalendar and an NSTimeZone to determine minutes, seconds, hours, months, years, etc.

Obj-C, problem formatting date, gaining a day?

I've discovered a bug in my app / function. I pass in a NSString of a date.
The function then uses the NSDateFotmatterShortStyle.
Heres a screen shot of my function in the debugger.
I'd like to end up with a date of 2011-04-18
Not sure why its added 1ppm either, I need it to be 00:00:00
Whats happening and how do I fix this ?
I use the MidnightUTC function from here ( How do I create the current date (or any date) as an NSDate without hours, minutes and seconds? ) to get rid of the hours.
I actually see no connection between the midnightUTC method and your provided code.
Anyway, the problem with your given example is that, the parsing of the string 4/18/11 will default the missing values like minutes etc AND your current time zone, but the string will be assumed as GMT time so this will result in the offset you see.
The solution is to set the time zone for the NSDateFormatter. Look at this code, I've tested it a minute ago, and the console output. aaa reveals the odd offset, bbb does look as expected.
NSDateFormatter *dt = [[[NSDateFormatter alloc] init] autorelease];
[dt setDateStyle:NSDateFormatterShortStyle];
NSDate *aaa = [dt dateFromString:#"4/18/11"];
NSLog(#"1a. %#", [dt timeZone]);
NSLog(#"1b. %#", aaa);
[dt setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"GMT"]];
NSDate *bbb = [dt dateFromString:#"4/18/11"];
NSLog(#"2a. %#", [dt timeZone]);
NSLog(#"2b. %#", bbb);
Console output
1a. Europe/Berlin (CEST) offset 7200 (Daylight)
1b. 2011-04-17 22:00:00 +0000
2a. GMT (GMT+00:00) offset 0
2b. 2011-04-18 00:00:00 +0000
the midnightUTC function you're using creates dates by setting the timeZone to GMT, which is different from UTC half the year. UTC doesn't observe any summer / daylight savings time changes, while GMT does, so [NSTimeZone timeZoneForSecondsFromGMT:0] will be an hour off UTC for roughly half the year.