1

我在将时间字符串转换为不同的时区时遇到问题。

这是我从服务器检索的字符串示例:@"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

来源日期字符串:2013 年 5 月 14 日凌晨 4 点 19 分

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

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

目的地日期字符串:2013 年 5 月 14 日上午 6 点 19 分


我要生气了!!!!

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

有什么提示吗?

谢谢

尼古拉


编辑

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

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)

目的地日期字符串:2013 年 5 月 14 日 10:19(正确)

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

来源日期字符串:2013 年 5 月 14 日晚上 10:19 -0400

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

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

目的地日期字符串:2013 年 5 月 14 日 22:19(错误!)

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

4

3 回答 3

1

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

在这里,您找到了时区,但未设置为 datefromatter。将时区设置为 dateformatter 并尝试

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

于 2013-05-14T09:47:13.060 回答
1

这就是你想要的:

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

于 2013-05-15T10:51:07.590 回答
0

谢谢大家的所有提示!经过大量试验,我最终编写了一个使用 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(我知道是 America/New_York)

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

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

于 2013-05-15T09:35:27.820 回答