I'm trying to work with dates and create dates in the future, but daylight savings keeps getting in the way and messing up my times.
Here is my code to move to midnight of the first day of the next month for a date:
+ (NSDate *)firstDayOfNextMonthForDate:(NSDate*)date
{
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
calendar.timeZone = [NSTimeZone systemTimeZone];
calendar.locale = [NSLocale currentLocale];
NSDate *currentDate = [NSDate dateByAddingMonths:1 toDate:date];
NSDateComponents *components = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
fromDate:currentDate];
[components setDay:1];
[components setHour:0];
[components setMinute:0];
[components setSecond:0];
return [calendar dateFromComponents:components];
}
+ (NSDate *) dateByAddingMonths: (NSInteger) monthsToAdd toDate:(NSDate*)date
{
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
calendar.timeZone = [NSTimeZone systemTimeZone];
calendar.locale = [NSLocale currentLocale];
NSDateComponents * months = [[NSDateComponents alloc] init];
[months setMonth: monthsToAdd];
return [calendar dateByAddingComponents: months toDate: date options: 0];
}
Which give the dates when I run the method iteratively on a date:
2013-02-01 00:00:00 +0000
2013-03-01 00:00:00 +0000
2013-03-31 23:00:00 +0000 should be 2013-04-01 00:00:00 +0000
2013-04-30 23:00:00 +0000 should be 2013-05-01 00:00:00 +0000
My initial thought was to not use systemTimeZone
but that didn't seem to make a difference. Any ideas for how I can make the time constant and not take into account the change in daylight savings?
For a given calendar date/time, it is not possible as a general rule to predict what actual time (seconds since the epoch) that represents. Time zones change and DST rules change. It's a fact of life. DST has a tortured history in Australia. DST rules have been very unpredictable in Israel. DST rules recently changed in the US causing huge headaches for Microsoft who was storing seconds rather than calendar dates.
Never save NSDate
when you mean NSDateComponents
. If you mean "the first of May 2013 in London," then save "the first of May 2013 in London" in your database. Then calculate an NSDate
off of that as close to the actual event as possible. Do all your calendar math using NSDateComponents
if you care about calendar things (like months). Only do NSDate
math if you really only care about seconds.
EDIT: For lots of very useful background, see the Date and Time Programming Guide.
And one more side note about calendar components: when I say "the first of May 2013 in London," that does not mean "midnight on the first of May." Don't go adding calendar components you don't actually mean.
Remember that what your program is printing to the log is the GMT time, not your local time. Therefore, it's correct for dates after the switch to DST in your local time zone that the GMT will have shifted by one hour.
I had the same problem, and people saying it's not actually a problem (as I saw on some related threads) doesn't help the situation. This kind of problem hurts whenever you have to deal with timezones and DST, and I always feel that I have to re-learn it every time.
I was dealing with epoch times as much as possible (it's a charting application), but there were times when I needed to use NSDate and NSCalendar (namely, for formatting the axis labels, and for marking calendar months, quarters and years). I struggled with this for a day or so, trying to set various timezones on calendars and suchlike.
In the end I found that the following line of code in my app delegate helped immensely:-
// prevent DST bugs by setting default timezone for app
if let utcZone = NSTimeZone(abbreviation: "UTC") {
NSTimeZone.setDefaultTimeZone(utcZone)
}
On top of this, the source data had to be sanitised, so whenever I used an NSDateFormatter
on incoming data, I made sure I set its time zone to the correct one for the data source (in my case, it was GMT). This gets rid of nasty DST issues in the data source and ensures all the resultant NSDates can be converted nicely into epoch times without worrying about DST.
来源:https://stackoverflow.com/questions/14570251/ios-create-date-in-the-future-ignoring-daylight-savings