objective-c:时区之间的转换

时间:2013-05-14 09:32:07

标签: objective-c nsdate nsdateformatter nstimezone

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

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

我知道timeZone是America / New_York,我想将其转换为我当地的时区:欧洲/罗马。

以下是我为测试而编写的代码:

-(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 TimeZone:GMT(GMT)偏移0

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

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

sourceOffset:4294952896 destinationOffset:7200 interval:21600

sourceDateString:5/14/2013 4:19 am

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

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

destinationDateString:05/14/2013 06:19 AM


我生气了!!!!

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

任何提示?

由于

尼古拉


修改

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

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

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

似乎有效,但事实并非如此。

我说“似乎”因为:

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

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

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

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

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

sourceDateString:5/14/2013 10:19 pm -0400

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

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

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

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

3 个答案:

答案 0 :(得分:1)

+0000组件定义带时区的日期并提供实际时间。一个NSDate对象也包含此部分。因为缺少部分时间差,相对于本地时区

这里你停止了时区,但没有设置为datefromatter。设置时区到dateformatter并尝试

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

答案 1 :(得分: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];
}

返回正确的输出:

原始日期时间:2013年5月13日上午04:19(我知道它是America / New_York)

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

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

答案 2 :(得分:0)

这就是你想要的:

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