NSDateFormatter reports June 2, 2013 as being in week zero - nsdate

I am using NSDateFormatter to convert a series of dates to a week number within a month.
The date formatting code I am using is yyyyMMW and everything I have read tells me that W will be between 1-5.
But, the 2nd of June 2013 fell on a Sunday (the default start day of the week in the gregorian calendar) and it's week number is reported as 0 even though the start date of the week is calculated correctly:
2013-06-03 14:15:45.611 date=20130531, week=2013055, start of week=20130526
2013-06-03 14:15:45.612 date=20130602, week=2013060, start of week=20130602
2013-06-03 14:15:45.612 date=20130603, week=2013061, start of week=20130602
Some quick and dirty test code to reproduce the log shown above:
NSDateFormatter *dateFormatDaily = [[NSDateFormatter alloc] init];
[dateFormatDaily setDateFormat:#"yyyyMMdd"];
NSDateFormatter *dateFormatterWeekly = [[NSDateFormatter alloc] init];
[dateFormatterWeekly setDateFormat:#"yyyyMMW"];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar setFirstWeekday:1]; // default but set here for clarity
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
[dateComponents setMonth:5];
[dateComponents setDay:31];
[dateComponents setYear:2013];
NSDate *date_1 = [calendar dateFromComponents:dateComponents];
[dateComponents setMonth:6];
[dateComponents setDay:2];
NSDate *date_2 = [calendar dateFromComponents:dateComponents];
[dateComponents setDay:3];
NSDate *date_3 = [calendar dateFromComponents:dateComponents];
NSArray *datesToTest = #[date_1, date_2, date_3];
for (NSDate *date in datesToTest) {
NSString *weekNo = [dateFormatterWeekly stringFromDate:date];
NSDate *beginningOfWeek = nil;
BOOL rc = [calendar rangeOfUnit:NSWeekCalendarUnit startDate:&beginningOfWeek interval:NULL forDate:date];
if (rc) {
NSLog(#"date=%#, week=%#, start of week=%#", [dateFormatDaily stringFromDate:date], weekNo, [dateFormatDaily stringFromDate:beginningOfWeek]);
} else {
NSLog(#"Could not calculate beginning of week");
}
}
Any ideas? A week number of 0 under any circumstances seems wrong to me.
Thanks

There are various parameters that cause this effect. First of all, you did not set a calendar for the date formatter. If you add
[dateFormatterWeekly setCalendar:calendar];
to your code, then the output will be as you expected:
date=20130531, week=2013055, start of week=20130526
date=20130602, week=2013062, start of week=20130602
date=20130603, week=2013062, start of week=20130602
But in your case, the date formatter uses the current calendar, and therefore has separate parameters firstWeekDay and minimumDaysInFirstWeek. These parameters are locale dependent. If I test this on the iOS Simulator with the "Region Format" set to "German -> Germany", then
[[dateFormatterWeekly calendar] firstWeekday] = 2
[[dateFormatterWeekly calendar] minimumDaysInFirstWeek] = 4
and I assume that you will have similar values, because now I get the same output as you.
Now for the date formatter, the week starts on a Monday, which means that June 2 is in the week starting at May 27. This counts as "week #0" in June, because only one day of this week is in June, but minimumDaysInFirstWeek = 4. The first week in a month that has at least
minimumDaysInFirstWeek days, counts as "week #1".
(I found the relevance of the minimumDaysInFirstWeek parameter here:
http://www.cocoabuilder.com/archive/cocoa/326845-week-of-month-confusion.html)

Related

How do you get the seconds since a past date to now?

How can I get the seconds that have passed since 1980-01-01 00:00:00 +1100 using NSTimeInterval?
// I need the function to use something like and am having an issue
NSDate *aDate = (NSDate*)#"1980-01-01 00:00:00 +1100";
NSDate *seconds = [NSDate dateWithTimeInterval:60*60*24 sinceDate:aDate];
NSLog(#"seconds since Jan 1980 %#",seconds);
// I am trying to replace the following
//NSTimeInterval dateinterval = [[NSDate date] timeIntervalSince1970];
NSTimeInterval dateinterval = seconds;
NSDate only retrieves the GMT at +0000 which is not helpful in real world applications. Local dates are mandatory.
Is this too hard or can it not be done this way?
You are initializing your NSDate object wrong. You can't directly cast an NSString as an NSDate, you need to use NSDateFormatter:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = #"yyyy-MM-dd HH:mm:ss z";
NSDate *aDate = [formatter dateFromString:#"1980-01-01 00:00:00 +1100"];
NSDate *now = [NSDate date];
NSTimeInterval seconds = [now timeIntervalSinceDate:aDate];
To format the date for a different time zone, use a new NSDateFormatter and set its local and timeZone.

NSdate repeating date for upcomming sunday

I am trying to create a date for next Sunday, and make it repeat for every Sunday after.
I know how to create the date using components, and components setWeek is depreciated, so I don't know how to do it now.
if You got the First Sunday Then You Should Do this To repeat it after seven Days!
NSString *sunday = #"Here Your Sunday Date";
NSDate *dateSunday = [self dateFromString:sunday];
[self GetNextSunday:dateSunday];
Then Call This Method To Get Next Sunday
-(void)GetNextSunday:(NSDate*)date
{
NSDate *NextSunday = [[NSDate alloc]init];
NSCalendar *gregorian = [[NSCalendar alloc]initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components = [gregorian components:( NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:date];
components.day = components.day + 8;
NextSunday = [gregorian dateFromComponents:components];
NSLog(#"%#",NextSunday);
}
This Will Return Next 7th Day ! I hope this Will Help You.
for Any Query Comment Below!

Get the last weekday of a month

I want to get the last weekday of a given month.
I've come across this simple answer on how to get the 1st/2nd/... weekday which works well.
The question is: How to get the last weekday of a given month?
Not every month has only 4 Sundays, so do I have to count the number of Sundays of the month, or is there a more elegant way to do this?
Had the same need recently, and the best I could come up with is the following, which is meant to be run every day to check if the current day is the last weekday of the current month:
<?php
$d = new DateObject('first day of this month', date_default_timezone());
$d->modify("+15 days");
$d->modify("first day of next month -1 weekday");
$last = date_format($d, 'd');
$today = new DateObject('today', date_default_timezone());
$today = date_format($today, 'd');
if ($today == $last) {
//bingo
}
?>
I have been testing and so far couldn't find an example where this fails. The reason for doing the modify("+15 days") in the middle is to be sure we are calling "next month" with a starting date that is not in the edge between two months, case where I believe this could fail.
Leaving the code shown before apparently covers all cases.
I finally came up with the following solution. I'm using NSDate-Extensions for convenience. dayOfWeek stands for Sunday (1) till Saturday (7) in the Gregorian calendar:
- (NSDate *)dateOfLastDayOfWeek:(NSInteger)dayOfWeek afterDate:(NSDate *)date
{
// Determine the date one month after the given date
date = [date dateByAddingMonths:1];
// Set the first day of this month
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
dateComponents.year = date.year;
dateComponents.month = date.month;
dateComponents.day = 1;
// Get the date and then the weekday of this first day of the month
NSDate *tempDate = [[NSCalendar currentCalendar] dateFromComponents:dateComponents];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *firstDayComponents = [gregorian components:NSWeekdayCalendarUnit fromDate:tempDate];
NSInteger weekday = firstDayComponents.weekday;
// Determine how many days we have to go back to the desired weekday
NSInteger daysBeforeThe1stOfNextMonth = (weekday + 7) - dayOfWeek;
if (daysBeforeThe1stOfNextMonth > 7)
{
daysBeforeThe1stOfNextMonth -= 7;
}
NSDate *dateOfLastDayOfWeek = [tempDate dateBySubtractingDays:daysBeforeThe1stOfNextMonth];
return dateOfLastDayOfWeek;
}

NSDateFormatterFullStyle api is giving different results

NSDateFormatterFullStyle api is giving different date formats in iPod and iPhone. In
iPhone : Friday, 21 December 2012 (coma is missed)
iPod : Friday, 21 December, 2012.
Sample code:
NSDate *date = [NSDate dateWithTimeIntervalSince1970:[postdateText doubleValue] / 1000.0];
NSLog(#"date %#:",date);
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[NSLocale currentLocale]];
NSString *dateString = [NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle];
NSTimeZone *tz = [NSTimeZone timeZoneWithName:#"CST"];
[dateFormatter setTimeZone:tz];
return dateString;
// I was tried in this way as well
//[dateFormatter setDateFormat:#"EEEE, MMMM dd, YYYY"];
//[dateFormatter setDateStyle:NSDateFormatterFullStyle];
That is changing depends on region format as well as language. Go to settings->General->International->Region Format. It should work.

dateFromString return nil after change 24 hour

NSDateFormatter *timeFormat = [[NSDateFormatter alloc] init];
[timeFormat setDateFormat:#"hh:mm a"];
NSDate* sourceDate = [timeFormat dateFromString:#"19/11/2010 12:00 am"];
if(sourceDate==nil)
{
NSLog(#"source date nil");
}
I'm using 24 hour setting in iPhone. After I change to 24 hour setting, datefromstring always return nil. I rechange to 12 hour format, it's working again. Why ?
The locale needs to be set to avoid being affected by the 24-hour setting change.
The format also has to match the input string (which in your example includes the date):
NSDateFormatter *timeFormat = [[NSDateFormatter alloc] init];
NSLocale *locale = [[[NSLocale alloc]
initWithLocaleIdentifier:#"en_US_POSIX"] autorelease];
[timeFormat setLocale:locale];
[timeFormat setDateFormat:#"dd/MM/yyyy hh:mm a"];
NSDate* sourceDate = [timeFormat dateFromString:#"19/11/2010 12:00 am"];
if(sourceDate==nil)
{
NSLog(#"source date nil");
}
See QA1480 for more information.

Resources