Wrong week from date component on IOS5 - ios

My region format is US, and I'm getting different week numbers from the ones I get on Mac OSx which is also in US.
I'm using iOS 5 and have not programmed on iOS before this sdk version. So I just want to make sure I'm not doing something wrong. Whit this code below I'm getting for the last week of the year the number 53 which I think is wrong. My first day of the week is set to sunday.
Please advice, thank you.
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDate *date = [NSDate date];
NSDateComponents *dateComponents = [calendar components:( NSWeekCalendarUnit) fromDate:date ];
int week = (int)[dateComponents week];
NSLog(#"%i", week);
Being [NSDate date] december 8, it returns week number 50, but on Mac OSX I get week 49

First off, I see you changed your code to get rid of the 'gregorianCalendar' nonsense. Good.
When I tried your code in a test app:
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponents = [calendar components:( NSWeekCalendarUnit) fromDate:[NSDate date]];
int week = (int)[dateComponents week];
[calendar release];
NSLog( #"week is %d", week);
return week;
I'm getting 49 (which makes sense to me).
If you're getting 53, then you're passing in the wrong date.

Did you check the locale? There are cases where the week numbers differ between the US and Europe for example.

Related

How to get current seconds left to complete hour?

I want to get how many seconds are remaining to complete an hour. No matter which what time it is?
if its 05:01:00 then it should give 3540 seconds
and if its 11:58:40 then it gives 80 seconds and so on. I try to find it on google but could not able to find it.
Thanks in advance.
NSCalendar has got methods to do that kind of date math:
NSDate *now = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
// find next date where the minutes are zero
NSDate *nextHour = [calendar nextDateAfterDate:now matchingUnit:NSCalendarUnitMinute value:0 options:NSCalendarMatchNextTime];
// get the number of seconds between now and next hour
NSDateComponents *componentsToNextHour = [calendar components:NSCalendarUnitSecond fromDate:now toDate:nextHour options:0];
NSLog(#"%ld", componentsToNextHour.second);
#Vadian's answer is very good. (voted)
It requires iOS 8 or later however.
There are other ways you could do this using NSCalendar and NSDateComponents that would work with older OS versions.
You could use componentsFromDate to get the month, day, year, and hour from the current date, then increment the hour value and use the NSCalendar method dateFromComponents: to convert your to adjusted components back to a date.
NSDate *date1 = [NSDate dateWithString:#"2010-01-01 00:00:00 +0000"];
NSDate *date2 = [NSDate dateWithString:#"2010-02-03 00:00:00 +0000"];
NSTimeInterval secondsBetween = [date2 timeIntervalSinceDate:date1];
Fill in with the correct times and dates to get the difference in seconds
Edit: An alternative method is to work out the currenthour and return as an integer. Then add one to the NSInteger returned as below (you will have to make sure to handle the case where it is after midnight though!)
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:[NSDate date]];
NSInteger currentHour = [components hour];

Finding the locale-dependent first day of the week

Given an NSDate, how do I find the first day of that date's week, given the user's locale. For example, I've heard that some countries treat Monday as the first day of the week and others use Sunday. I need to return the preceding Monday in the first case but the preceding Sunday in the latter case.
My best effort thus far always returns the preceding Sunday, regardless of the device settings applied:
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setLocale:[NSLocale currentLocale]];
NSDateComponents *components = [calendar components:NSYearForWeekOfYearCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSWeekCalendarUnit | NSWeekdayCalendarUnit fromDate:originalDate];
[components setWeekday:1];
NSDate *firstDayOfWeek = [calendar dateFromComponents:components];
Bonus question: on iOS, which setting drives this? Is it the 'Region Format'?
Try changing:
[components setWeekday:1];
to:
[components setWeekday:[calendar firstWeekday]];
You should also remove the NSYearForWeekOfYearCalendarUnit and NSWeekCalendarUnit components.
Bonus Question: "Region Format" should be the setting that changes the first day of the week.
An smarter way for old style for those who do not want to set calendar firstWeekday.
NSDate *date = [NSDate dateWithTimeIntervalSince1970:1483620311.228];
NSLog(#"current date ===> : %#", date);
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate *previousMonday = [calendar nextDateAfterDate:date
matchingUnit:NSCalendarUnitWeekday
value:2 //use 1-7 for Sunday to Saturday week day.
options:NSCalendarMatchNextTime | NSCalendarSearchBackwards];
NSLog(#"previousMonday date ===> : %#", previousMonday);

Numeric value: day of the week

Im changing text value based on the day of the week, I was able to achieve this using string values, however I want to be able to achieve on a numeric value instead - to remove issues with different languages. For example, if today is monday do... but I want if today is day 1 then do. Ive tried the code below but it gives me a numeric value of 0;
NSDateFormatter *dayofweekformatter = [[NSDateFormatter alloc] init];
[dayofweekformatter setDateFormat:#"E"];
NSString *DayOfWeek = [dayofweekformatter stringFromDate:[NSDate date]];
NSInteger weekDay = [DayOfWeek integerValue];
NSLog(#"The day of the week is: %d", weekDay);
Is it possible to do this?
According to this link, "E" on its own will give you the day of the week as a textual format, i.e.: "Mon"/"Tue" etc.
If you want the day of the week as an integer, you should use a lower case "e" or "c".
A different implementation would be to use NSCalendar and NSDateComponents to determine the day of the week as this is more likely to take into consideration different settings across different devices based on the users preferred calendar.
NSDate *date = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponents = [calendar components:NSCalendarUnitWeekday fromDate:date];
NSLog(#"day of the week: %i", [dateComponents weekday]);
Here is solution proposed on Apple forums https://discussions.apple.com/thread/1700102?start=0&tstart=0 (I am not the author)
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *weekdayComponents =[gregorian components:NSWeekdayCalendarUnit fromDate:dateOfInterest];
NSInteger weekday = [weekdayComponents weekday];
// weekday 1 = Sunday for Gregorian calendar
[gregorian release];

NSDate of the week

I an using the current methods to get the first and the last day of the current week:
NSDate *weekDate = [NSDate date];
NSCalendar *myCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *currentComps = [myCalendar components:( NSYearCalendarUnit | NSMonthCalendarUnit | NSWeekOfYearCalendarUnit | NSWeekdayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate:weekDate];
[currentComps setWeekday:1]; // 1: sunday
NSDate *firstDayOfTheWeek = [myCalendar dateFromComponents:currentComps];
[currentComps setWeekday:7]; // 7: saturday
NSDate *lastDayOfTheWeek = [myCalendar dateFromComponents:currentComps];
This was working perfect, but now in ios 4.3 and it's not working.
Any idea what can be the problem?
I have started Xcode 4.1 on my OS X 10.6 partition and tried to compile your code against the iOS 4.3 SDK. It turned out that NSWeekOfYearCalendarUnit is undefined, so that must have been introduced in later iOS versions. This might explain why it does not work on iOS 4.3.
The following alternative code works and gives the correct result:
NSDate *now = [NSDate date];
NSCalendar *myCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *firstDayOfTheWeek;
NSTimeInterval length;
[myCalendar rangeOfUnit:NSWeekCalendarUnit
startDate:&firstDayOfTheWeek
interval:&length
forDate:now];
NSDate *lastDayOfTheWeek = [firstDayOfTheWeek dateByAddingTimeInterval:length];
Update: The above code gives the (start of) the first day in the week and the (start of) the next week. If you add (length - 1) instead of length then you will get the end of the last day in the week (thanks #rmaddy!). Alternatively, you can add 6 days to the first day:
NSDate *now = [NSDate date];
NSDate *firstDayOfTheWeek;
NSCalendar *myCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[myCalendar rangeOfUnit:NSWeekCalendarUnit
startDate:&firstDayOfTheWeek
interval:NULL
forDate:now];
NSDateComponents *sixDays = [[NSDateComponents alloc] init];
[sixDays setDay:6];
NSDate *lastDayOfTheWeek = [myCalendar dateByAddingComponents:sixDays toDate:firstDayOfTheWeek options:0];
Remark: This code also handles the "start of week" correctly according to the locale.
Your third component, NSWeekOfYearCalendarUnit, is only available as of iOS 5. See https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSCalendar_Class/Reference/NSCalendar.html. I believe for what you are doing, you don't need that component, you should be able to just remove it.
As for the localization comments from the others on this post, they are correct that things change in different locales, but not the way you might expect. Sunday is indeed always day 1 (and Saturday day 7), but in cultures where Monday is the first day of the week, your code will return the following Saturday and the following Sunday, seemingly at the end of the week. You can fix this by explicitly setting your calendar to use the en-US locale, or attempt to account for other locales by using the firstDayOfWeek property. You can test this by switching the Region Format of you simulator to German > Germany, in Settings > General > International > Region Format.
It's unclear in which sense you are having difficulties, but it might be simply that there's no consensus on which is the first day of the week.
[old example redacted; Mike below correctly pointed out that it was invalid]
Per the NSDateComponents documentation, "For example, in the Gregorian calendar, n is 7 and Sunday is represented by 1."; if your device is using any of the nine other calendars supported by iOS — such as the Buddhist, Chinese or Hebrew calendars — then Apple doesn't guarantee that Sunday is day 1.

iOS Finding the time passed since a specific date

I have been playing with NSDate and NSTimeInterval to try and get the time passed since a specific date, but I am not having much luck.
I want to specify an exact constant date (Jan 5th 2012 2PM) and calculate the time passed in Years, Hours, Min, Sec and display this on the screen as a counter.
It seems simple enough; however, browsing through code has yet to prove successful for me.
I also want to see total time in a years months days mins secs format. I appreciate any help, thanks!
This an example I have found that I don't know how to customize:
NSCalendar *c = [NSCalendar currentCalendar];
NSDate *d1 = [NSDate date];
NSDate *d2 = [NSDate dateWithTimeIntervalSince1970:1340323201];//2012-06-22
NSDateComponents *components = [c components:NSHourCalendarUnit fromDate:d2 toDate:d1 options:0];
NSInteger diff = components.minute;
NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit
Like tkanzakic said,
NSDateComponents* components = [c components:(NSYearCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit) fromDate:d1 toDate:d2 options:0] ;
NSLog(#"%ld years, %ld hours, %ld minutes, %ld seconds", components.year, components.hour, components.minute, components.second) ;

Resources