I searched it a lot but coudn't find any instance of showing how to store the specified time. For example, i need to save time of 15:48 in code in a proper variable (i guess that should be NSDate object). That is needed because i want to hold the exact time to replace the method below with not the time interval since now but my exact specified time to fire notification. Thanks for the help.
NSDate *notificationDate = [NSDate dateWithTimeIntervalSinceNow:5];
notification.fireDate = notificationDate;
Use NSDateComponents:
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setHour:15]; // 15:48 from your example
[comps setMinute:48]; // 15:48 from your example
/// also set year, month and day
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:comps];
[comps release];
You can also use NSDateCompnents to read the components from the current date and time - so if you want to set an NSDate to 15:48 today, you would first create an NSDate for now and then extract the day, month and year from it but overwrite the hour and minutes.
Use NSDateComponents to generate an NSDate object. I guess the Apple document is what you want http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSDateComponents_Class/Reference/Reference.html
Take a look at NSDateFormatter and especially - (NSDate *)dateFromString:(NSString *)string
Related
I am using UIDatePickerView, just like we can set the date range using "maximumDate" and "minimumDate", is there any way to set time range in a day like from 9.00 am to 6.00 pm ?
Not really. minimumDate and maximumDate can include a time of day (NSDate is more like a timestamp than a calendar date), but this only has an effect if they are both on the same day because otherwise all (clock) times are possible within the date range.
Actually you should set the time using these two as well. NSDate objects have both date and time components. You should do something like this:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
//set the date using setDate: setMonth: setYear:
[dateComponents setHour:9]; //setHour:18 for maximumDate
NSDate *targetDate = [gregorian dateFromComponents::dateComponents];
[dateComponents release];
[gregorian release];
datepick.minimumDate = targetDate;
If that doesnt help, have a look at these Qs:
UI Datepicker range. iPhone
How to set time on NSDate?
This should be really simple!
I have a shop, it opens at 8:30 and closes at 17:00. I want my app to say the shops current open or currently closed.
Whats the best way to store my open_time and close_time? Store them as seconds since the start of the day, i.e. 30600 and 63000?
This make sense, but how do I get the current time right now, in seconds since the begining of today, so I can check if current_time is between open_time and close_time, i.e. open!!
Thanks in advance!
This problem isn't quite as trivial as you may think. You have to work with dates very carefully. The best solution is to store all of your open and close times as dates. Here is some code for creating your open/close times and comparing them:
NSDate * now = [NSDate date];
NSCalendar * calendar = [NSCalendar currentCalendar];
NSDateComponents * comps = [calendar components:~(NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:now];
[comps setHour:8];
[comps setMinute:30];
NSDate * open = [calendar dateFromComponents:comps];
[comps setHour:17];
[comps setMinute:0];
NSDate * close = [calendar dateFromComponents:comps];
if ([now compare:open] == NSOrderedDescending && [now compare:close] == NSOrderedAscending) {
// The date is within the shop's hours.
}
else {
// The date is not within the shop's hours.
}
Here's what I did:
Grab the current date.
Get the components of the date, except hours, minutes, and seconds.
Set the hour and minutes.
Create an open time.
Repeat steps 3-4 for close time.
Compare open and close times to now.
If you ever need to do any modification of dates, you should always use NSCalendar and NSDateComponents. Check out this answer for why it's so important.
I think a clearer solution would be to use NSDate objects with only hour/minute components present.
Basically, somewhere in your app you need to store the shop's open/close times as such:
NSCalendar *calendar = [[NSCalendar alloc]
initWithCalendarIdentifier: NSGregorianCalendar];
NSDateComponents *openTime = [[NSDateComponents alloc] init];
[openTime setHour: 12];
[openTime setMinute: 30];
NSDate *openDate = [calendar dateFromComponents: openTime];
[calendar release];
And if you need to see whether the current time is between two such NSDate objects you could have a method like this:
- (BOOL)currentTimeIsInBetween: (NSDate *)date1 andDate: (NSDate *)date2 {
NSCalendar *calendar = [[NSCalendar alloc]
initWithCalendarIdentifier: NSGregorianCalendar];
NSDateComponents *currentComponents = [calendar components:
(NSMinuteCalendarUnit | NSHourCalendarUnit)
fromDate: [NSDate date]];
NSDate *currentAdjusted = [calendar dateFromComponents: currentComponents];
[calendar release];
if ([currentAdjusted compare: date1] == NSOrderedAscending)
return NO;
if ([currentAdjusted compare: date2] == NSOrderedDescending)
return NO;
return YES;
}
EDIT: Seems like user rbrown was a bit faster than me, we are suggesting the same approach.
You can do something like this.
NSDate *today = // code for getting today date at 0 oclock
NSDate *now = [NSDate date];
double second = [now timeIntervalSinceDate:today];
Now you got time in second since the start of the day for compare.
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.
I have been trying to wrap my head around NSDate, NSCalendar, NSDateComponents, NSTimeZone, and NSDateFormatter.
NSDate, NSTimeZone and NSDateFormatter are pretty straightforward. The other classes are not.
I want to get the current Eastern Time (the actual date/time is in EST at the moment the code is run).
Then I want to advance that date by exactly one month, taking into account daylight savings that may (or may not be) in effect.
From what I understand, adding 84600 is the improper way to do this, but I could be wrong.
Can someone please post an example of how to do this?
It's actually pretty easy:
NSDate *now = [NSDate date];
NSDateComponents *oneMonth = [[[NSDateComponents alloc] init] autorelease];
[oneMonth setMonth:1];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *oneMonthFromNow = [calendar dateByAddingComponents:oneMonth toDate:now options:0];
NSDateFormatter *df = [[[NSDateFormatter alloc] init] autorelease];
[df setTimeZone:[NSTimeZone timeZoneWithName:#"America/New_York"]];
[df setDateStyle:NSDateFormatterMediumStyle];
[df setTimeStyle:NSDateFormatterMediumStyle];
NSLog(#"Now in New York: %#", [df stringFromDate:now]);
NSLog(#"One month from now in New York: %#", [df stringFromDate:oneMonthFromNow]);
Edit: That said, your question is phrased a little confusingly. With NSDate, you don't do calculations in a specific time zone. You also don't get the "current Eastern Time". You just get the current point in time (regardless of time zone) and do your calculations on it. The actual conversion to a specific time zone only happens at output (when you display the time to the user, usually in their time zone).
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.