NSDateComponents specifying AM/PM? - iphone

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.

Related

NSPredicate filter array, for NSDate

i have an array of NSManagedObject take from my core data, and i want filter the array with the date that is >= of today, so i do this:
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(firstAired >= %#)", [NSDate date]];
but find me only the date > of today, and the date of today don't, why?
You should create Midnight date,like this, and pass it to the predicate
NSDateComponents *currentComponents = [[NSCalendar currentCalendar]components:NSMinuteCalendarUnit|NSHourCalendarUnit|NSSecondCalendarUnit fromDate:[NSDate date]];
[currentComponents setMinute:0];
[currentComponents setHour:0];
[currentComponents setSecond:0];
NSCalendar *calendar = [[NSCalendar alloc]initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *dateToCheck = [calendar dateFromComponents:currentComponents];
NSDate *now = [NSDate date];
NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
NSDateComponents *components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:now];
[components setHour:00];
NSDate *today = [calendar dateFromComponents:components];
in this way works, thanks to all...
[NSDate date] is the current time. So this predicate will fetch only records where firstAired is later today or later, and not earlier today. Construct an NSDate with the time 00:00:00.
Because [NSDate date] returns the exact date with hour, minute, second .... of the instant when it is executed. If you want to search for every "today" item then you have to change [NSDate date] with a NSDate object for today at midnight. That is, extract the date components from NSDate.date and then, using the components year, month and day build a new date object with hour: 00:00AM.

IOS 4.1 NSDateComponents giving differing date then later versions of IOS

I have created an NSDate category that would give me a "last sunday" date.
+(NSDate *)sunday{
// I need 2 dates yesterday and today
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *now = [NSDate date];
NSLog(#"Current date: %#", now);
NSDateComponents *components = [gregorian components:(NSWeekCalendarUnit | NSWeekdayCalendarUnit ) fromDate:now];
[components setWeekday:1]; //Monday
[components setHour:0]; //8a.m.
[components setMinute:0];
[components setSecond:0];
NSLog(#"Sunday: %#", [gregorian dateFromComponents:components]);
return [gregorian dateFromComponents:components];
}
This give me a couple different dates:
IOS 4.2
Sunday: 0001-08-28 05:50:36 +0000
IOS 4.1
Sunday: 0001-09-04 05:50:36 GMT
Notice
That IOS 4.1 give me a future date, whereas IOS 4.2 gives me a previous date, which is what I want.
I understand that the year is 0001 is shown, but the year is not used.
I have not yet found where others are having this same issue, so perhaps I'm doing something wrong. But, I'm not sure what that is. Has anyone seen this before?
EDIT
Here is my working code:
+(NSDate *)sunday{
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *now = [NSDate date];
NSDateComponents *components = [gregorian components:(NSWeekCalendarUnit | NSYearCalendarUnit | NSWeekdayCalendarUnit ) fromDate:now];
[components setWeekday:[gregorian firstWeekday]]; //Sunday
[components setHour:0];
[components setMinute:0];
[components setSecond:0];
return [gregorian dateFromComponents:components];
}
Thanks!!
You should probably reconsider your assertion that the year is not used. Sure, 2011-09-04 and (by the Julian calendar used by NSGregorianCalendar for dates before 1582-10-15) 0001-09-04 are both Sundays so it seems like it doesn't matter. But next year it won't match up.
Your problem with the differing results on the two devices is most likely that your devices are set to different regions, with different rules about which day is the first day of the week or which week is the first of the year. You can check the firstWeekday property on your NSCalendar object to determine the first, and minimumDaysInFirstWeek will help with the latter.

How can I create a date with no hours in the current time zone?

This question follows on from a previous question...
How do I create the current date (or any date) as an NSDate without hours, minutes and seconds?
I would use this code as follows...
NSDate *todaysDate = [General makeAbsoluteNSDate:[NSDate date]];
My problem is that I have users in different countries and UTC isn't their timezone and the date produced by this function at certain times of the day won't be correct.
How do I get the current time zone to correct my function ?
Or should I be using a different approach ?
Heres the function I've been using...
+ (NSDate *)makeAbsoluteNSDate:(NSDate*)datSource {
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:
NSGregorianCalendar];
[calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"]];
NSDateComponents *dateComponents = [calendar components:NSYearCalendarUnit |
NSMonthCalendarUnit | NSDayCalendarUnit
fromDate:datSource];
[dateComponents setHour:0];
[dateComponents setMinute:0];
[dateComponents setSecond:0];
NSDate *midnightUTC = [calendar dateFromComponents:dateComponents];
[calendar release];
return midnightUTC;
}
You get the timezone object from this call:
[NSTimeZone localTimeZone]
And you can use the secondsFromGMT method to figure out the difference and create a date with the timezone.
You can even build a Category for NSDate that includes a method to transform a date into the current timezone date, which would be even simpler.

create NSDate Object representing "today" at a certain Time

I'm either a bit overwhelmed by the complexity of NSDate or I simply don't understand the concept of it :)
The only thing I want to do is to create an NSDate Instance representing today's date and a fixed time of 20.00h respectively 8pm.
This can't be as difficult as creating an instance holding the current time and afterwards either subtracting oder adding the neccessary difference to 8pm, can it?
Thanks for your help...
the ultranoob
Use NSCalendar:
NSCalendar* myCalendar = [NSCalendar currentCalendar];
NSDateComponents* components = [myCalendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
fromDate:[NSDate date]];
[components setHour: 20];
[components setMinute: 0];
[components setSecond: 0];
NSDate *myDate = [myCalendar dateFromComponents:components];

Get all days of any month with objective-c

A seemingly simple question...how can I return a list of days for any specified month?
NSDate *today = [NSDate date]; //Get a date object for today's date
NSCalendar *c = [NSCalendar currentCalendar];
NSRange days = [c rangeOfUnit:NSDayCalendarUnit
inUnit:NSMonthCalendarUnit
forDate:today];
I basically want to use that, but replace today with say, the month of January, so I can return all of those days
Carl's answer works on Mac. The following works on Mac or iPhone (no dateWithNaturalLanguageString: available there).
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
// Set your year and month here
[components setYear:2015];
[components setMonth:1];
NSDate *date = [calendar dateFromComponents:components];
NSRange range = [calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date];
NSLog(#"%d", (int)range.length);
You can make your date with pretty much any string:
NSDate *date = [NSDate dateWithNaturalLanguageString:#"January"];
Then the rest of your code will work as-is to give you back the NSRange for the number of days in January.