使用夏令时的NSDateFormatter时间字符串不正确

时间:2015-02-10 17:35:59

标签: ios objective-c swift nsdate nsdateformatter

我在我的应用程序中使用CET作为我的默认timezone。在德国Daylight节省时间将从 2015年3月29日开始。现在我正在做一些测试,以确定我的日期将来是否会正确转换。我使用以下代码来测试它。

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]);

添加月份的类别方法是

- (NSDate *)dateByAddingMonths:(NSInteger) dMonths {
    NSDateComponents *components = [[NSDateComponents alloc] init];
    components.month = dMonths;
    NSCalendar *calendar = [NSCalendar currentCalendar];
    return [calendar dateByAddingComponents:components toDate:self options:0];
}

控制台的输出如下:

NOW DATE -> 2015-02-10 18:28:05 +0100
DATE AFTER 29 March -> 2015-04-10 18:28:05 +0200

我在3月29日之后的预计时间是17:28:05,因为在白天之后现在减少了1小时。我究竟做错了什么?

PS:我还尝试在标签中设置输出字符串,不会发生任何变化。

3 个答案:

答案 0 :(得分:2)

我真的不明白你在抱怨什么。

您要求操作系统添加两个月的日期。添加两个月意味着它使用日历,并在同一时间返回两个月后的日期,即该月的同一天。 将DST中的更改考虑在内,并且确实如此。这就是增加两个月的意思。

想象一下,我们会在本月的第一天,上午10点开会。无论是否是DST,您都希望在早上10点开会。

答案 1 :(得分:1)

试试这个;

[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]);

它对我来说很好。查看日志

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

答案 2 :(得分:0)

您可以使用nextDaylightSavingTimeTransition查找您所在时区的下一个夏令时转换的时间:

NSTimeZone(abbreviation: "CET")!.nextDaylightSavingTimeTransition!   // "Mar 28, 2015, 22:00"

您可以创建一个NSDateFormatter扩展来使用CET时区格式化您的时间,如下所示:

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"