【问题标题】:objective-c: Conversion between TimeZonesObjective-c:时区之间的转换
【发布时间】:2013-05-08 12:36:02
【问题描述】:

我在将时间字符串转换为其他时区时遇到问题。

这是我从服务器检索的字符串示例:@"5/14/2013 4:19am"

我知道时区是 America/New_York,我想将其转换为我的本地时区:Europe/Rome。

这是我为测试它而编写的代码:

-(void) convertTimeZone
{   

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.timeZone=[NSTimeZone timeZoneWithAbbreviation:@"GMT"];
    dateFormatter.dateFormat=@"MM/dd/yyyy HH:mma";
    NSString *sourceDateString = @"5/14/2013 4:19am";

    NSTimeZone *sourceTimeZone = [[NSTimeZone alloc] initWithName:@"America/New_York"];
    NSTimeZone *destinationTimeZone = [NSTimeZone localTimeZone];
    NSInteger sourceGMToffset = sourceTimeZone.secondsFromGMT;
    NSInteger destinationGMToffset = destinationTimeZone.secondsFromGMT;
    NSInteger interval = destinationGMToffset-sourceGMToffset;


    NSLog(@"DateFormatter TimeZone: %@", dateFormatter.timeZone);
    NSLog(@"Source TimeZone: %@", sourceTimeZone);
    NSLog(@"Destination TimeZone: %@", destinationTimeZone);
    NSLog(@"sourceOffset: %u destinationOffset: %u interval: %u", sourceGMToffset, destinationGMToffset, interval);

    NSLog(@"----------------------------------------------------------------------------------------------------");

    NSLog(@"sourceDateString : %@", sourceDateString);

    //Convert from string to date

    NSDate *dateObject = [dateFormatter dateFromString:sourceDateString];
    NSLog(@"From string to date: %@", dateObject);

    //Now back from date to string
    NSLog(@"From date to string: %@", [dateFormatter stringFromDate:dateObject]);

    //Convert from sourceTimeZone to destinationTimeZone
    NSDate *newDate = [[NSDate alloc] initWithTimeInterval: interval sinceDate:dateObject];     
    NSLog(@"destinationDateString: %@", [dateFormatter stringFromDate: newDate]);

}

输出


DateFormatter 时区:GMT (GMT) 偏移量 0

来源时区:America/New_York (GMT-04:00) 偏移量 -14400(日光)

目标时区:本地时区(欧洲/罗马 (CEST) 偏移 7200(日光))

sourceOffset:4294952896 destinationOffset:7200 间隔:21600

sourceDateString : 5/14/2013 4:19am

从字符串到日期:2013-05-14 00:19:00 +0000

从日期到字符串:05/14/2013 00:19AM

destinationDateString:05/14/2013 06:19AM


我要生气了!!!!

如果原始日期是“5/14/2013 4:19am”为什么日期格式化程序将其更改为“05/14/2013 00:19AM”????????? 如果它已正确保存到“05/14/2013 04:19AM +0000”,则转换将是完美的(两个时区之间为 6 小时)!!!

有什么提示吗?

谢谢

尼古拉


编辑

按照 lithu-t-v 的建议设置这些参数:

dateFormatter.timeZone=[NSTimeZone timeZoneWithAbbreviation:@"GMT"];

NSString *sourceDateString = @"5/14/2013 4:19am -0400";

它似乎有效,但它没有。

我说“似乎”是因为:

sourceDateString:5/14/2013 04:19am -0400

从字符串到日期:2013-05-13 04:19:00 +0000 (OK)

从日期到字符串:05/14/2013 04:19 (OK)

destinationDateString:05/14/2013 10:19(正确)

是正确的,但如果我在下午晚些时候尝试:

sourceDateString:2013 年 5 月 14 日晚上 10:19 -0400

从字符串到日期:2013-05-14 16:19:00 +0000(错误)

从日期到字符串:05/14/2013 16:19

destinationDateString:05/14/2013 22:19(错误!)

正确的结果应该是:05/15/2013 04:19AM

【问题讨论】:

  • 谢谢,但问题似乎在于从 STRING 到 DATE 的转换。
  • 将其转换为夏令时+0000,然后根据时区计算时间。
  • 问题在从字符串到日期的转换中。请参阅下面的答案,但有两个问题 1. 您使用了不正确的小时说明符,2 您使用了不正确的时区,您应该使用 NY 时间进行第一次转换。

标签: objective-c nsdate nsdateformatter nstimezone


【解决方案1】:

+0000 组件定义带有时区的日期并提供实际时间。NSDate 对象也包括这部分。由于缺少该部分,因此相对于本地时区的时差来了

在这里你找到了时区,但没有设置为 datefromatter。将时区设置为 dateformatter 并尝试一下

将 +0000 附加到字符串并执行剩余的操作。它将起作用

【讨论】:

  • 如果我像这样更改我的 dateFormatter.dateFormat 和 sourceDateString: dateFormatter.dateFormat=@"MM/dd/yyyy HH:mma Z"; NSString *sourceDateString = @"5/14/2013 4:19am +0000";我仍然得到相同的输出:5/14/2013 4:19am +0000 从字符串到日期:2013-05-14 00:19:00 +0000 我不认为这是问题。
  • @NicolaP。 :最简单的方法是将 +0000 附加到您的字符串并执行剩余的
【解决方案2】:

感谢大家的所有提示! 经过大量试验,我最终编写了一个使用 DateComponent 的函数:

-(NSString*) convertToLocalTimeZoneDate: (NSString*) sourceDate
                                   Time: (NSString*) sourceTime
{
    //Date and time parsing

    //Expected: NSString *sourceDate = @"5/13/2013";
    //Expected: NSString *sourceTime = @"04:19am";

    NSArray *dateArray = [sourceDate componentsSeparatedByString:@"/"];
    NSDateComponents *dateComps = [[NSDateComponents alloc] init];
    dateComps.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    dateComps.year = [[dateArray objectAtIndex:2] integerValue];
    dateComps.month = [[dateArray objectAtIndex:0] integerValue];
    dateComps.day = [[dateArray objectAtIndex:1] integerValue];

    NSString *timeInDay = [sourceTime substringFromIndex:5];

    if ([[timeInDay uppercaseString] isEqualToString:@"PM"]){
        dateComps.hour = 12 + [[sourceTime substringWithRange:NSMakeRange(0, 2)] integerValue];
    } else {
        dateComps.hour = [[sourceTime substringWithRange:NSMakeRange(0, 2)] integerValue];
    }

    dateComps.minute = [[sourceTime substringWithRange:NSMakeRange(3, 2)] integerValue];
    dateComps.timeZone = [[NSTimeZone alloc] initWithName:@"America/New_York"];

    NSLog(@"Original Date Time: %@ %@", sourceDate, sourceTime);
    NSLog(@"GMT Date Time: %@", dateComps.date);

    //Return a string with the local date and time

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.locale = [NSLocale currentLocale];
    dateFormatter.dateStyle = NSDateFormatterShortStyle;
    dateFormatter.timeStyle = NSDateFormatterLongStyle;

    return[dateFormatter stringFromDate:dateComps.date];
}

它返回正确的输出:

原始日期时间:5/13/2013 04:19am(我知道是美国/纽约)

GMT 日期时间:2013-05-13 08:19:00 +0000 (OK)

输出:13/05/13 10:19:00 CEST

【讨论】:

    【解决方案3】:

    这就是你想要的:

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat=@"dd/MM/yyyy h:mma"; // Note:  lower case h
    NSString *sourceDateString = @"14/5/2013 5:19am"; // in New Yourk
    
    NSTimeZone *sourceTimeZone = [[NSTimeZone alloc] initWithName:@"America/New_York"];
    NSTimeZone *destinationTimeZone = [NSTimeZone localTimeZone];
    dateFormatter.timeZone = sourceTimeZone;
    
    NSLog(@"DateFormatter TimeZone: %@", dateFormatter.timeZone);
    NSLog(@"Source TimeZone: %@", sourceTimeZone);
    NSLog(@"Destination TimeZone: %@", destinationTimeZone);
    
    NSLog(@"---------------------------------------");
    
    NSLog(@"sourceDateString : %@", sourceDateString);
    
     //Convert from string to date
    
    NSDate *dateObject = [dateFormatter dateFromString:sourceDateString];
    NSLog(@"From string to date should be in GMT: %@", dateObject);
    
    //Convert from sourceTimeZone to destinationTimeZone
    dateFormatter.timeZone = destinationTimeZone;
    NSLog(@"Hopefully works: %@", [dateFormatter stringFromDate: dateObject]);
    

    输出:

    Test Case '-[TestOrderedList testFoo]' started.
    2013-05-15 11:44:04.263 LogicSim[43238:303] DateFormatter TimeZone: America/New_York (EDT) offset -14400 (Daylight)
    2013-05-15 11:44:04.264 LogicSim[43238:303] Source TimeZone: America/New_York (EDT) offset -14400 (Daylight)
    2013-05-15 11:44:04.264 LogicSim[43238:303] Destination TimeZone: Local Time Zone (Europe/London (BST) offset 3600 (Daylight))
    2013-05-15 11:44:04.264 LogicSim[43238:303] ---------------------------------------
    2013-05-15 11:44:04.264 LogicSim[43238:303] sourceDateString : 14/5/2013 5:19am
    2013-05-15 11:44:04.265 LogicSim[43238:303] From string to date should be in GMT: 2013-05-14 09:19:00 +0000
    2013-05-15 11:44:04.265 LogicSim[43238:303] Hopefully works: 14/05/2013 10:19AM
    Test Case '-[TestOrderedList testFoo]' passed (0.002 seconds).
    

    您犯的第一个错误是日期格式规范HH 是24 小时格式的时间。当与 am/pm 说明符一起使用时,这似乎总是将小时解析为 0。您的测试数据恰好有 4 小时,这与 GMT 和纽约之间的偏移量相同,导致您假设它只是得到偏移错误。我将小时说明符更改为 h 以获得 12 小时的时间。我还更改了测试时间,以减少混乱。

    第二个错误是弄乱了 NSDate 对象,那是精神错乱。 NSDate总是在 GMT 中。不要添加或减去时间间隔来更正时区,只需在日期格式化程序中适当地设置时区即可。所以我的代码将时区设置为纽约并解析日期。然后它将时区设置为当地时间(我在英国的英国夏令时)并将日期字符串化。任务完成。

    【讨论】:

      猜你喜欢
      • 2017-03-05
      • 2011-03-09
      • 1970-01-01
      • 1970-01-01
      • 2016-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-17
      相关资源
      最近更新 更多