How to get number of current week in objective-c? - iphone

I develop an app that needs to get the current week. I tried this:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *dateString = #"1-1-2011";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd-MM-yyyy"];
NSDate *dateFromString = [[NSDate alloc] init];
dateFromString = [dateFormatter dateFromString:dateString];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comp = [gregorian components:NSWeekCalendarUnit fromDate:dateFromString];
NSLog(#"%d", comp.week);
[dateFormatter release];
}
but it shows me 52. Which is actually a wrong result. Please, suggest me any ideas.
Thanks in advance.

The week date depends on which numbering standard is in use. For instance, the ISO-8601 standard defines week 1 of a year as "the week with the year's first Thursday in it".
The first of January 2011 was a Saturday, which means the following week was week 1 of 2011, making the week 27.12.2010–2.1.2011 week 52 of 2010.
Also, there's several incompatible standards for when weeks start or end and how weeks in a year are numbered. This makes week numbers a confusing way to specify a date range and the best solution to avoid using them.
From the documentation to NSCalendar, it seems you could also use setMinimumDaysInFirstWeek: to adjust the way it numbers weeks.

Related

How to get date from day of the year in iPhone?

How do I get date from the day of the year?
for e.g., if I give day as "1" then date should be "January 1"
How do I get that in iPhone? I have found answer in javascript but I want to know how to do the achieve same thing in Objective?
I guess this code will work for you:
I have created a sample function where a textfield gives input values for how many days to add. And a button to calculate final day. Here is the button event logic.
NSDateComponents *dateComponent = [[NSDateComponents alloc] init];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-mm-dd"];
NSDate *newDate = [formatter dateFromString:#"2012-01-01"];
// add days to current date
dateComponent.day = [dayTextField.text intValue];
// get a new date by adding components
newDate = [[NSCalendar currentCalendar] dateByAddingComponents: dateComponent toDate:newDate options:0];
[finalDate setText:[NSString stringWithFormat:#"%#", newDate]];
Here dayTextField.text is the text which says how many number of days want to calculated. (For example 125 days) and finalDate is an label which displays final generated date (means date after 125 days since 1 Jan 2012).
Benefit of this code is, any time you can change the start day parameter. For example, for other requirement, i need to count my days from "31 May 1999" then i will change it easily in one line and the same code will work.
Enjoy Coding :)
NSCalendar *gregorian =
[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger dayOfYear =
[gregorian ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSYearCalendarUnit forDate:[NSDate date]];
[gregorian release];
return dayOfYear;
Take from the post:
How do you calculate the day of the year for a specific date in Objective-C?

Comparing NSDates to determine day or night?

I'm parsing a weather XML that gives me the sunrise + sunset times for the user's location. I've parsed them as strings, and they look like this: 7:20 am and 5:34 pm, for example.
I then converted these two times into an NSDate by doing this:
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"hh:mm a"];
NSDate *Sunrise = [dateFormat dateFromString:sunrise];
NSDate *Sunset = [dateFormat dateFromString:sunset];
NSDate *today = [NSDate date];
[dateFormat release];
Now I have three dates which I now want to compare to determine whether the current time is night or day. The problem is, when I NSLog the Sunrise and Sunset times I see that the year is 1970 on both the dates that came from strings. I don't know where to start on how to compare the dates. Any ideas?
Theres actually a pretty simple way to do this. NSDateFormatter has a method called setDefaultDate: which basically uses a given date object to fill in any fields not included by the date format string. So, using the variables from your sample:
[dateFormat setDefaultDate:today];
Just put this line before the calls to dateFromString:, and you should be good to go.
Reference: NSDateFormatter Class Reference
You may split up a NSDate into Date Components, you'll need a NSCalendar Object and tell it to give you a NSDateComponents Instance for your date.
Like so:
NSCalendar *gregorian = [NSCalendar currentCalendar];
NSUInteger unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDate *date = [NSDate date];
NSDateComponents *comps = [gregorian components:unitFlags fromDate:date];
NSLog(#"Parts: Day %d, Month %d, Year %d", [comps day], [comps month], [comps year]);
Instead of the example "unitFlags" you may OR together any of the NS*CalenderUnit Flags to get the corresponding elements into "comps". In your case it would be something like NSHourCalenderUnit | NSMinuteCalenderUnit .
Try altering your sunrise and sunset NSString variables to contain the current date. Something like "2010-12-15 7:20am". Once you parse that, your Sunrise and Sunset dates will be correct, and the comparison should be easy.

Getting NSDate for today with 00:00:00 as time

I am writing a categorie in Xcode, that would extend the current NSDate class. I want to add two methods which I use regularly and somehow I can't get them to work properly.
Currently I have this code:
+ (NSDate*) today
{
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *todayComponents = [gregorian components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:[NSDate date]];
NSInteger theDay = [todayComponents day];
NSInteger theMonth = [todayComponents month];
NSInteger theYear = [todayComponents year];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:theDay];
[components setMonth:theMonth];
[components setYear:theYear];
NSDate* todayDate = [gregorian dateFromComponents:components];
[components release];
[gregorian release];
return todayDate;
}
I want it to return a date like this: "2010-11-03 00:00:00 +01". But somehow the timezone keeps buggin me, because this code returns "2010-11-02 23:00:00 +0000".
Can anyone tell me how to fix this code to actually return the correct date? Or can I just use this date and my application will convert it itself because of the timezone the machine is set to.
I have to log certain events in my app to a database, which also just uses the [NSDate date] method. Does that mean that the [NSDate date] method also uses the time without timezone information?
EDIT:
I think it has something to do with the Daylight savings time bug. The things I see is exactly the same as probably the Clock app has, with the bug making people wake up late. Also, the TimeZone defaults to the TimeZone currently set on your device, so it should stay the same until you change the timezone in your settings screen.
EDIT2:
Ok, some more tests:
NSLog(#"CurrentDate: %#", [NSDate date]);
NSLog(#"TZ: %#", [NSTimeZone defaultTimeZone]);
Gives me the following results:
2010-11-03 23:23:49.000 App[8578:207] CurrentDate: 2010-11-03 22:23:49 +0000
2010-11-03 23:23:49.001 App[8578:207] TZ: Europe/Amsterdam (GMT+01:00) offset 3600
See Using Time Zones. You'll want to set the calendar's time zone using NSCalendar's -setTimeZone: method before you start asking it for dates.
This is an interesting question and I worked at a solution for many hours. These are my findings:
NSLog(#"CurrentDate: %#", [NSDate date]);
The code shown above will have the same result as the code shown below:
NSLog(#"CurrentDate: %#", [[NSDate date] description]);
Reading through the NSDate Class Reference produces this documentation on the NSDate's description method.
The representation is not guaranteed to remain constant across different releases of the operating system. To format a date, you should use a date formatter object instead (see NSDateFormatter and Data Formatting Guide)
I also ran across the documentation for descriptionWithLocale: (id) locale:
“Returns a string representation of the receiver using the given locale.”
So, change your code
NSLog(#"CurrentDate: %#", [NSDate date]);
To:
NSLog(#"CurrentDate: %#", [[NSDate date] descriptionWithLocale:[NSLocale currentLocale]]);
Which should result in what you are looking for. And I can also prove that the [NSDate date] really give's the correct date, but is just being displayed with wrong method:
We can use the [today] (Wim Haanstra) to create two dates.
dateLastDay: 2010-11-02 23:59:00 +01
dateToday: 2010-11-03 24:01:00 +01
Then we use the code below to show the two dates:
NSLog(#"CurrentDate: %#", dateLastDay);
NSLog(#"CurrentDate: %#", dateToday);
Or:
NSLog(#"CurrentDate: %#", [dateLastDay description]);
NSLog(#"CurrentDate: %#", [dateToday description]);
The two groups show the same results, like this: "2010-11-02 22:59:00 +0000" and "2010-11-02 23:01:00 +0000". It looks like the two dates have the same ‘day’, but really?
Now we compare the days of the dates:
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger unitFlags = NSDayCalendarUnit;
NSDateComponents *lastDayComponents = [gregorian components:unitFlags fromDate:dateLastDay];
NSDateComponents *todayComponents = [gregorian components:unitFlags fromDate:dateToday];
NSInteger lastDay = [lastDayComponents day];
NSInteger today = [todayComponents day];
return (lastDay == today) ? YES : NO;
We will get NO! Although the two dates appear to have the same day, month and year, they DON'T. It only appears that way because we displayed them in the wrong way.
Did you try using:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd"];
todayAtOO = [formatter dateFromString:[formatter stringFromDate:[NSDate date]]];
I'm still trying to figure out exactly why this bug happens, but I do know a solution. Setting the timezone of your NSCalendar to GMT before sending it dateFromComponents: will solve the issue.
[gregorian setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
PS if there's a different solution that you found based on Joshua's suggestion, could you let us know what it is? It seems like you've solved the issue since you accepted his answer, but it's not really clear what you did. Thanks!
As far as I can see, it is giving you the correct answer if your timezone is GMT+1. Midnight your time is 23:00 the day before in GMT.
The problem is probably in formatting the returned date for output. It's given you a string for GMT instead of your current locale.

Is Friday with date format "c" returned as 5 or 6?

Initially I thought that using this code
+ (NSString *)getDayOfTheWeek:(NSDate *)date format:(NSString*)format
{
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
dateFormatter.dateFormat = format;
NSString *formattedDateString = [dateFormatter stringFromDate:date];
NSLog(#"Des pico je: %#",formattedDateString);
return formattedDateString;
}
NSDate *now = [NSDate date];
NSString *today = [self getDayOfTheWeek:now format:#"c"]
should return a string with a number for each day, but it gets different results for different regional format settings. (Mon = 1 or Sun = 1) and maybe some variations. don't know. So is there a common way to get this solution generically for all region date type settings on iPhone easily?
The "c" is the stand-alone local day of week. Stand-alone means it's meant to be used without any further date context (as opposed to "e"). And the local day of week is dependent on the locale, i.e. which day does the locale dictate as being the first day of the week. So Friday can be either 5 or 6, depending on the locale.
To find out which day is the first day of the week you can use [[NSCalendar currentCalendar] firstWeekday].
But if you want just a string with the name of today's day, as in "Monday", "Tuesday", etc. you can use NSString *today = [self getDayOfTheWeek:now format:#"cccc"];.

Create an NSMutableArray using NSCalendar

I have following problem: I need to create an NSMutabeArray with every weekday after a specific date.
This should look like:
Thursday 28 october 2010
Thursday 04 october 2010
Thursday 11 october 2010
...
How can I do that? I think it has something to do with NSCalendar, but I can't find the right solution... Could you help me?
Thank you in advance
FFraenz
That's an infinite series; an NSMutableArray can only hold a finite collection.
At any rate, you need only a single member of the series, such as 2010-10-28. To get the Thursday after that, add one week. To get the third date in the series, add a week to the second date, or two weeks to the first date. Having any member of the series provides you with access to any other member of the series.
If you are starting from a date that isn't the right weekday, get the date components for that date, add the difference between the correct weekday and the weekday it has to its day of the month, and convert the amended date components back to a date. That date will then be on the desired weekday in the same week.
To have actual date:
NSDate *today = [[NSDate alloc] init];
To add a week:
NSDate *nextDate = [today dateByAddingTimeInterval:60*60*24*7];
Then you can iterate and create your array:
NSMutableArray* dates = [[NSMutableArray alloc] init];
NSDate *date= [[NSDate alloc] init];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setWeek:1];
for (int i=0;i<10;i++) {
NSDate *nextDate = [gregorian dateByAddingComponents:offsetComponents toDate:date options:0];
[dates addObject:date];
[date release];
date = nextDate;
}
[date release];