NSDate with no time - objective-c

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".

Related

How to show human readable NSDate using NSDateFormatter

I need to show human readable NSDate localized Format.
Currently, NSDateFormatter can only format one date at a time.
But, I could find any example on how to do two dates format.
Here are some examples of format I need to produce.
10:00 - 11:00AM
Monday 25th March, 2013
10:00AM - 11:00PM
Monday 25th March, 2013
and also these need to be in localized format depend on locale and timezone.
Could any one shade some lights here ? Thank you very much.
Regardless of how you will approach this, you will have to take two strings and combine them together.
When it boils down to it, you ultimately have two dates:
10:00 - 11:00AM Monday 25th March, 2013
^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Date1 Date2
You can use two separate NSDateFormatter objects to give you what you need.
NSDateFormatter *timeOnlyDateFormatter = [[NSDateFormatter alloc] init];
//... set the format for the timeOnlyDateFormatter here
NSDateFormatter *fullDateFormatter = [[NSDateFormatter alloc] init];
//.. set the format for the fullDateFormatter here
With this, you can use them to create both the Date1 string and Date2 string, then combine them.
NSString *firstString = [timeOnlyDateFormatter stringFromDate:firstDate];
NSString *secondString = [fullDateFormatter stringFromDate:secondDate];
NSString *combined = [NSString stringWithFormat:#"%# - %#", firstString, secondString];
There's no real pretty way to do this as far as I know.

Storing an absolute NSDate, not relative to a timezone

I am creating an iOS app to track attendance. Each attendance entry is stored in an object which has a status attribute (e.g. present, absent) and an NSDate attribute called date which denotes the day which that attendance record was taken. When I select a particular date (using a UIDatePickerView or alike) I want all the attendance records (objects) for that date to appear in a table view.
While this sounds simple in principle, I am running into an issue relating to timezones. I am aware that NSDates are stored independent of timezones (i.e. they are stored relative to UTC/GMT +0000). This means that if I am in Sydney and take attendance on, for example, Sunday 4 November 2012 because the date is stored as timezone independent, if I take my iPhone/iPad to a different time zone (such as San Francisco) all the attendance records would shift one day back, in this case to Saturday 3 November 2012, because that was the moment in time when the attendance was taken in San Francisco local time (which was actually the next day, in Sydney local time).
I don't want this to happen - I want the date to be absolute. In other words, if the attendance is taken on Sunday 4 November 2012 then it needs to stay on that date, no matter where in the world (and whichever timezone) I may go. As you can see, this is quite in contrast to, say, a calendar application where it is desirable for the timing of appointments to change depending on the timezone.
Any suggestions on a better way to approach this problem would be appreciated. Please keep in mind that I am selecting the date to display using a UIDatePickerView which returns the current NSDate in the timezone independent format, so I also need a way to do an easy comparison (preferably in an NSPredicate since the attendance objects are stored in Core Data) to get all the attendance objects for that particular day.
Have you tried converting the time to it's NSDateComponents? you can then recreate an NSDate from it regardless of the time zone.
Edited to add
// This is just so I can create a date from a string.
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd HH:mm:ss z"];
// Create a date as recorded in a timezone that isn't mine.
NSDate *localDate = [formatter dateFromString:#"2012-10-30 10:30:00 +0200"];
NSLog(#"Initial Date: %#", localDate);
// this logs 2012-10-30 08:30:00 +0000
// Which is what you would expect, as the original time was 2 hours ahead
NSDateComponents *components = [[NSDateComponents alloc] init];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
components = [gregorian components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit fromDate:localDate];
NSLog(#"Components: %#", components);
// Create a date from these time components in some other time zone
[gregorian setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"EST"]];
NSDate *newDate = [gregorian dateFromComponents:components];
NSLog(#"New Date: %#", newDate);
// This logs 2012-10-30 12:30:00 +0000
// Which is the local EST of 8:30 am expressed in UTC
Which demonstrates how I can turn make 8:30 am in +2 time zone look the same as for a -4 timezone.
I believe the better way for you is to use timestamp since it independ of any time zone. You can use vary methods to convert timestamps to date and back. And implement any logic you wish.
Also you can easily compare them.

NSDate Output incorrectly [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Getting date from [NSDate date] off by a few hours
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"M-d-yyyy H:mm"];
NSDate *start= [dateFormatter dateFromString:#"10-24-2012 12:15"];
NSDate *end = [dateFormatter dateFromString:#"10-24-2012 15:30"];
When I print out
NSLog(#"------main_event start %#", start);
NSLog(#"-----main_event end %#", end);
The result is
---main_event start 2012-10-24 19:15:00 +0000
---main_event end 2012-10-24 22:30:00 +0000
Now, it looks like the time added 7 hours automatically, 12:15 becomes 19:15, and 15:30 becomes 22:30.
Why?
because the timezone, where your device is located, is UTC-7.
The output is in UTC (hence the +0000), as a single NSDate will always print out it's time in UTC.
If you use an NSDateFormatter to output the date, it will take your locale in account. See my answer here: NSDate date method returns wrong result
These are correct results. When you use NSLog to output an NSDate object, it displays in GMT. The parsing was done in your local timezone. NSDate objects are alway in GMT. If you want to print the NSDate object in your local timezone then you need an NSDateFormatter to print the date.

How to convert NSString to NSDate?

I want to search my Array of Dictionary for particular date.Ex I want to search my array of dictionary for date "16 Jan 2012" which is in string format but my dictionary item in array contains date and time, say "16 Jan 2012 somehours:somemins:somesecs".I am converting string format date in NSDate format but I am getting date as 2012-01-15 18:30:00 +0000 instead of 2012-01-16.I am using NSPredicate to search for the date which convert date into seconds as follows "Date == CAST(348345000.000000, "NSDate")" and compare so even though my records contain date as "16 Jan 2012 somehours:somemins:somesecs" it will not satisfied the criteria.I want that the records/array containing date as "16 Jan 2012 somehours:somemins:somesecs" should satisfied the search criteria.Please can anyone know how to achieve this?
Thanks in advance!
To rid yourself of NSDateFormatter's automatic adjustment for your time zone use something like this.
dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
To elaborate; "16 Jan 2012" Contains no hour, minute, or seconds value, so when parsing it with an NSDateFormatter one would expect an NSDate with a description of "2012-01-16 00:00:00 +000" But that's not what you're getting because the date formatter is adjusting for the 5:30 Hours between GMT and India?(Assuming based on :30 differential). By setting the date formatter's time zone explicitly you avoid this problem.
You need to use NSDateFormatters to convert the date string from one format to another. You can have an inputDateFormatter where you use dateFromString to give you an NSDate, and then feed this into an outputDateFormatter which gives your desired string.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd MMM yyyy"];
NSString *dateInFormatYouWant = [dateFormatter stringFromDate:yourDate]
I'm not sure if there is a more efficient way of doing it than this.

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.