I am trying to create the NSDate object with date "1 oct 2013 8:00:00". I used the following code
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setYear:2013];
[components setMonth:10];
[components setDay:1];
[components setHour: 8];
[components setMinute: 00];
[components setSecond: 00];
NSDate *date = [calendar dateFromComponents:components];
But when i print the date it gives wrong time "2013-10-01 02:30:00 +0000"
This happens because of time zone: you are in the Indian Standard Time (IST) zone, which lags 5 hours and 30 minutes behind GMT. When you set NSDate to 8:00 from the components, it uses your time zone, so the result gets adjusted to 02:30 so that NSDate has the correct GMT time. If you would like to set the time to 08:00 GMT, set your components' timeZone to GMT:
[components setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"GMT"]];
Related
Why is this giving me the wrong date ?
NSCalendar *myCalendar = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];
NSDateComponents* components = [myCalendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:[NSDate date]];
[components setYear:2013];
[components setMonth:06];
[components setDay:28];
[components setHour:5];
[components setMinute:00];
NSDate *startDate1 = [myCalendar dateFromComponents:components];
NSLog(#"start date is %#",startDate1);
start date is 2013-06-28 03:00:00 +0000
EDIT
What I want to do is the following. I have a start and endate.
For example:
start date is 2013-06-28 05:00
end date is : 2013-06-29 04:59
Then I want to check if the current date is between start and end date. I am using the following.
NSComparisonResult result1 = [now compare:startDate1];
NSComparisonResult result2 = [now compare:endDate1];
if (result2 == NSOrderedSame && result1 == NSOrderedSame ) {
NSLOG(#"OKE!");
}
Probably the date is correct, but you misunderstood the log:
Logging a date is always done in TZ +0000. For example, if you are in central europe, you will have the (expected?) date 2013-06-28 05:00:00 +0200, but the log will display the normilzed date 2013-06-28 03:00:00 +0000. This is the same date and time! It is simply expressed in a different way.
+++
If your components are in TZ +0000, too, you should set the time zone of the calendar.
You can check whether the current date is between two dates like this:
NSDate *now = [NSDate date];
BOOL betweenStartAndEnd = ([startDate compare:now] == NSOrderedAscending && [endDate compare:now] == NSOrderedDescending);
Your code actually checks whether the tested date is EQUAL (NSOrderedSame) to both start and end dates (which is not of course)
result2 == NSOrderedSame && result1 == NSOrderedSame
See my extended example:
NSCalendar *myCalendar = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];
NSDateComponents* components = [myCalendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:[NSDate date]];
[components setYear:2013];
[components setMonth:05];
[components setDay:13];
[components setHour:18];
[components setMinute:00];
NSDate *startDate = [myCalendar dateFromComponents:components];
[components setDay:15];
NSDate *endDate = [myCalendar dateFromComponents:components];
NSDate *now = [NSDate date];
BOOL betweenStartAndEnd = ([startDate compare:now] == NSOrderedAscending && [endDate compare:now] == NSOrderedDescending);
NSLog(#"Date %# %# between %# and %#", now, betweenStartAndEnd ? #"IS" : #"IS NOT", startDate, endDate);
This prints out this to the console:
Date 2013-05-13 15:44:06 +0000 IS NOT between 2013-05-13 16:00:00 +0000 and 2013-05-15 16:00:00 +0000
That's because you have to print the date using device's time zone, otherwise it's shown in UTC.
NSCalendar *myCalendar = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];
NSDateComponents* components = [myCalendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:[NSDate date]];
[components setYear:2013];
[components setMonth:06];
[components setDay:28];
[components setHour:5];
[components setMinute:00];
NSDate *startDate1 = [myCalendar dateFromComponents:components];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.timeZone = [NSTimeZone systemTimeZone];
formatter.dateFormat = #"yyyy-MM-dd HH:mm:ss";
NSLog(#"%#", [formatter stringFromDate:startDate1]);
I am building up a date using NSDateComponents from the following string:
"2014-05-17 02:39:00 PM +0000"
When I set all the components and return an NSDate I am getting (see method below):
"2014-05-17 02:39:00 AM +0000"
My question is, is there a way to specify the AM/PM to NSDateComponent, or do I just have to add 12 to my hour if the source date is PM?
- (NSDate *)dateFromYear:(int)year month:(int)month day:(int)day hour:(int)hour minute:(int)minute {
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"]];
[components setYear:year];
[components setMonth:month];
[components setDay:day];
[components setHour:hour];
[components setMinute:minute];
NSCalendar *calendar = [NSCalendar currentCalendar];
return [calendar dateFromComponents:components];
}
Apparently, NSDateComponents doesn't seem to specify this.
Apple's own docs on it says this:
Important: An NSDateComponents object is meaningless in itself; you
need to know what calendar it is interpreted against, and you need to
know whether the values are absolute values of the units, or
quantities of the units.
Apart from your 12 hours logic, you can alternately use NSDate class dateWithNaturalLanguageString that uses AM/PM and make use it somehow for your purpose.
I frequently use the NSDate compare method - but I want to consider two dates similar if they are equal in year, month, day. I have made a procesure called "cleanDate" to remove the hour part before I compare.
-(NSDate*)cleanDate:(NSDate*)date {
NSCalendarUnit unitflags;
NSDateComponents *component;
NSCalendar *calendar;
calendar=[[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]autorelease];
unitflags=NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
component=[calendar components:unitflags fromDate:date];
return [calendar dateFromComponents:component]; //Dato uten klokke
}
But my dates come out as:
2011-10-28 22:00:00
and some dates as:
2011-10-28 23:00:00
I want the hour part to be similar, e.g. 00:00.
Whats wrong? Does it have something to do with daylight saving time? Other? Thanks.
-(NSDate*)cleanDate:(NSDate*)date {
NSDateComponents *comps = [[NSCalendar currentCalendar]
components:NSDayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit
fromDate:date];
[comps setHour:0];
[comps setMinute:0];
[comps setSecond:[[NSTimeZone systemTimeZone] secondsFromGMT]];
return [[NSCalendar currentCalendar] dateFromComponents:comps];
}
Seems like this is a Time Zone issue...
I thought NSLog would default to the local time zone - but it seems to default to GMT...
Date with GMT time zone is: Sat, 29 Oct 2011 22:00:00 GMT+00:00
Date with system time zone is: Sun, 30 Oct 2011 00:00:00 GMT+02:00
NSlog shows 2011-10-29 22:00:00 +0000
When using NSLog(#"NSlog shows %#",finalDate); it seems to print the GMT time...
When using this code - I will get the local date in my time zone:
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:#"EEE, d MMM yyyy HH:mm:ss z"];
[dateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
NSString *dateString = [dateFormatter stringFromDate:myDate];
NSLog(#"Date with system time zone is: %#",dateString);
... so my original cleanDate actually seems to do what I want after all...
I think this is just a minor problem. After searching for some time I still can't figure it out. Hopefully you can. :-)
I want to get a full timestamp of today, passing own hours and minutes.
My approach was the following(dateStr is #"11:30" for example):
NSDateFormatter *myFormatter = [[[NSDateFormatter alloc] init] autorelease];
[myFormatter setTimeZone:[NSTimeZone systemTimeZone]];
[myFormatter setDateFormat:#"HH:mm"];
NSDate *tmpDate = [myFormatter dateFromString:dateStr];
[myFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss ZZZ"];
...???
So now I get
1970-01-01 11:30:00 +0000
What do I habe to do to apply the dateStyle to my NSDate and get the correct date of today?
I know that I can use [NSDate date] to get the actual date but what can I do to "manipulate" only minutes and hours?
Would be great to get some help from you guys :)
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorian components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:[NSDate date]];
[components setHour:hour];
[components setMinute:minute];
NSDate *date = [gregorian dateFromComponents:components];
[gregorian release];
I created a method to find the third Friday of every month.
When I run it from Eastern time zone, all is well.
When I run it from Central, the dates are off.
My method:
-(NSDate*) getSaturdayAfterThirdFriday:(NSDate*)date {
NSDate* resultDate = nil;
if( date != nil ) {
NSDateFormatter *df = [[NSDateFormatter alloc] init];
// start at the 1st of the month
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSTimeZone *zone = [NSTimeZone timeZoneWithName:#"EST"];
[calendar setTimeZone:zone];
NSDateComponents *comp = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:date];
[comp setDay:1];
date= [calendar dateFromComponents:comp];
[calendar release];
// count number of 'fri' (including today)
BOOL foundFlag = NO;
NSString* dateString = nil;
NSInteger count = 0;
[df setDateFormat:#"EEE"];
while (foundFlag == NO) {
dateString = [df stringFromDate:date];
if( [dateString caseInsensitiveCompare:#"fri"] == 0 ) {
count++;
NSLog(#"Found Friday: %#", [date description]);
}
if( count >= 3 ) foundFlag = YES;
else date = [NSDate dateWithTimeInterval:86400 sinceDate:date];
}
// get the next day (Saturday)
resultDate = [NSDate dateWithTimeInterval:86400 sinceDate:date];
[df release];
}
return resultDate;
}
The date that is passed is created with this method:
-(NSDate*) getDateForEasternTime:(NSDate*)date {
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSTimeZone *zone = [NSTimeZone timeZoneWithName:#"EST"];
[calendar setTimeZone:zone];
NSDateComponents *comp = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:date];
date = [calendar dateFromComponents:comp];
[calendar release];
NSLog(#"getDateForEasternTime: %#", [date description]);
return date;
}
I need to calculate dates based on Eastern Time only.
Here's my log output for Eastern time zone:
getDateForEasternTime: 2010-11-14 05:00:00 GMT
Found Friday: 2010-11-05 05:00:00 GMT
Found Friday: 2010-11-12 05:00:00 GMT
Found Friday: 2010-11-19 05:00:00 GMT
And for Central Time:
getDateForEasternTime: 2010-11-14 05:00:00 GMT
Found Friday: 2010-11-05 05:00:00 GMT
Found Friday: 2010-11-13 05:00:00 GMT
Found Friday: 2010-11-20 05:00:00 GMT
What's even more strange is that if I go further West in time zones, there is the discrepancy. If I go East in time zones there is none.
Any NSDate guru's can help with this?
Edit:
When I refer to changing the time zone, I'm talking about changing the time zone on the device itself. The line:
NSTimeZone *zone = [NSTimeZone timeZoneWithName:#"EST"];
Remains unchanged.
All your code is unnecessary. Using the weekday and weekdayOrdinal properties of NSDateComponents you can directly query a NSCalendar for the 3rd Friday of a month:
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setWeekday:6]; // 1 = Sunday ... 7 = Saturday
[components setWeekdayOrdinal:3]; // 3rd Friday
[components setMonth:11];
[components setYear:2010];
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
NSDate *date = [currentCalendar dateFromComponents:components];
Also, there is almost the same example for this in the Developer Documentation.