I'm using CET
as my default timezone
in my application. In Germany Daylight
saving time will start from 29 March 2015. Now I'm doing some testing to see if my dates will be converted correctly in the future. I used following code to test it.
NSTimeZone *timeZone = [NSTimeZone timeZoneWithAbbreviation:@"CET"];
[NSTimeZone setDefaultTimeZone:timeZone];
NSDate *now = [NSDate date]; // 10 Feb, 2015
NSDate *dateAfter29March = [now dateByAddingMonths:2]; // 10 April, 2015
NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss ZZZ"];
[formatter setTimeZone:timeZone];
NSLog(@" NOW DATE -> %@",[formatter stringFromDate:now]);
NSLog(@" DATE AFTER 29 March -> %@",[formatter stringFromDate:dateAfter29March]);
The category method for adding months is
- (NSDate *)dateByAddingMonths:(NSInteger) dMonths {
NSDateComponents *components = [[NSDateComponents alloc] init];
components.month = dMonths;
NSCalendar *calendar = [NSCalendar currentCalendar];
return [calendar dateByAddingComponents:components toDate:self options:0];
}
The Output of Console is as follows:
NOW DATE -> 2015-02-10 18:28:05 +0100
DATE AFTER 29 March -> 2015-04-10 18:28:05 +0200
Where my expected time on date after 29 March was 17:28:05 as One hour in now less after daylight time. What am I doing wrong?
PS: I also tried to set the output strings in a label and no change occurs.
I really don't see what you are complaining about.
You asked the OS to add two months to a date. And adding two months means that it uses the calendar, and returns a date that is two months later, on the same day of the month, at the same time. It should take changes in DST into account, and it does. That's what adding two months means.
Imagine we have a meeting that we always do at the first of the month, at 10am in the morning. You want that meeting at 10am in the morning, whether it is DST or not.
Try this;
[NSTimeZone setDefaultTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate *now = [NSDate date]; // 10 Feb, 2015
NSDate *dateAfter29March = [self dateByAddingMonths:2 date:now]; // 10 April, 2015
NSLog(@"now -> %@", now);
NSLog(@"dateAfter29March -> %@", dateAfter29March);
NSLog(@"========================================");
NSTimeZone *timeZone = [NSTimeZone timeZoneWithAbbreviation:@"CET"];
NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss ZZZ"];
[formatter setTimeZone:timeZone];
NSLog(@"NOW DATE -> %@",[formatter stringFromDate:now]);
NSLog(@"DATE AFTER 29 March -> %@",[formatter stringFromDate:dateAfter29March]);
It worked fine for me. See the logs
now -> 2015-02-11 06:01:56 +0000
dateAfter29March -> 2015-04-11 06:01:56 +0000
========================================
NOW DATE -> 2015-02-11 07:01:56 +0100
DATE AFTER 29 March -> 2015-04-11 08:01:56 +0200
You can use nextDaylightSavingTimeTransition to find out when is the next daylight saving time transition for your time zone:
NSTimeZone(abbreviation: "CET")!.nextDaylightSavingTimeTransition! // "Mar 28, 2015, 22:00"
You can create a NSDateFormatter extension to format your time using the CET time zone as follow:
extension NSDate {
var time:String {
let formatter = NSDateFormatter()
formatter.timeZone = NSTimeZone(abbreviation: "CET")
formatter.dateFormat = "HH:mm"
return formatter.stringFromDate(self)
}
}
let futureDate = NSCalendar.currentCalendar().dateWithEra(1, year: 2015, month: 3, day: 27, hour: 13, minute: 0, second: 0, nanosecond: 0)!
let futureDateDLST = NSCalendar.currentCalendar().dateWithEra(1, year: 2015, month: 3, day: 29, hour: 13, minute: 0, second: 0, nanosecond: 0)!
futureDate.time // 17:00"
futureDateDLST.time // "18:00"