使用NSDateFormatter将UTC转换为本地时间

时间:2014-05-09 12:32:39

标签: cocoa cocoa-touch time nsdateformatter date-parsing

我从iOS应用中的服务器获取以下字符串:

  

20140621-061250

如何将其转换为当地时间?

如何定义日期格式化程序?这是对的吗?

dateFormatter.dateFormat = @"YYYYMMd-HHmmss"; 

3 个答案:

答案 0 :(得分:36)

问题并没有明确指定转换的含义,但是无论最终目标如何,您应该做的第一件事就是使用正确配置的{{1}来正确解析服务器响应}}。这需要指定正确的格式字符串,并且必须在格式化程序上明确设置时区,否则它将从本地时间推断出来,这在大多数情况下是不正确的。

指定格式字符串

让我们看看提供的输入字符串:

  

20140621-061250

这使用年份的四位数字,月份的两位数字(零填充),以及当天使用的两位数(可能是零填充)。接下来是NSDateFormatter,然后是两位数表示小时,2位数表示分钟,2位数表示秒。

参考Unicode date format standards,我们可以通过以下方式派生格式字符串。表示日历年的四位数字将替换为格式字符串中的-。本月使用yyyy,当天使用MM。接下来是文字dd。对于小时数,我假设它将采用24小时格式,否则此响应不明确,因此我们使用-。然后是分钟HH和秒mm。连接格式说明符会产生以下格式字符串,我们将在下一步中使用它:

ss

在我们的计划中,这看起来像:

yyyyMMdd-HHmmss

配置输入日期格式化程序

上面的时间格式没有指定时区,但是因为您已经为服务器响应提供了表示UTC时间的规范,我们可以将其编码到我们的应用程序中。因此,我们实例化NSString *dateFormat = @"yyyyMMdd-HHmmss"; ,设置正确的时区,并设置日期格式:

NSDateFormatter

将输入字符串转换为NSTimeZone *inputTimeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; NSDateFormatter *inputDateFormatter = [[NSDateFormatter alloc] init]; [inputDateFormatter setTimeZone:inputTimeZone]; [inputDateFormatter setDateFormat:dateFormat];

出于演示目的,我们对从服务器响应中收到的字符串进行硬编码;您将使用从服务器获取的NSDate替换此inputString的定义:

NSString *inputString = @"20140621-061250";
NSDate *date = [inputDateFormatter dateFromString:inputString];

此时,我们有必要的对象来进行任何进一步的转换或计算 - NSDate表示服务器传达的时间。请记住,NSDate只是一个时间戳 - 它与时区无关,只有在转换到日期的字符串表示形式或从日历的字符串表示形式转换时才起作用,或通过{{1 }}

后续步骤

问题并没有明确指出需要什么类型的转化,因此我们会看到格式化日期的示例,以与服务器响应相同的格式显示(尽管如此,我可以'想一想这个特定代码的可能用例,说实话)。步骤非常相似 - 我们指定格式字符串,时区,配置日期格式化程序,然后从日期生成一个字符串(以指定的格式):

NSDateComponents

由于我在UTC-06:00,打印NSTimeZone *outputTimeZone = [NSTimeZone localTimeZone]; NSDateFormatter *outputDateFormatter = [[NSDateFormatter alloc] init]; [outputDateFormatter setTimeZone:outputTimeZone]; [outputDateFormatter setDateFormat:dateFormat]; NSString *outputString = [outputDateFormatter stringFromDate:date]; 给出以下内容:

  

20140621-001250

如果您向用户显示此日期,或者使用的话,您可能会想要使用outputStringsetDateStyle:而不是格式字符串setTimeStyle:获取NSCalendar实例以对该日期进行算术运算或计算。向用户显示详细日期字符串的示例:

NSDateComponents

在此处打印NSTimeZone *outputTimeZone = [NSTimeZone localTimeZone]; NSDateFormatter *outputDateFormatter = [[NSDateFormatter alloc] init]; [outputDateFormatter setTimeZone:outputTimeZone]; [outputDateFormatter setDateStyle:NSDateFormatterFullStyle]; [outputDateFormatter setTimeStyle:NSDateFormatterFullStyle]; NSString *outputString = [outputDateFormatter stringFromDate:date]; 为我们提供了以下内容:

  

2014年6月21日(星期六)上午12:12:50山区白天时间

请注意,适当设置时区将处理夏令时的转换。将输入字符串更改为" 20141121-061250"使用上面的格式化程序样式代码为我们提供了以下日期(请注意,Mountain Standard Time是UTC-7):

  

2014年11月20日星期四下午11:12:50山地标准时间

摘要

每当您以表示日历日期和时间的字符串形式获取日期输入时,您的第一步是使用为输入格式,时区和可能的区域设置配置的outputString进行转换和日历,取决于输入的来源和您的要求。这将产生NSDateFormatter,这是一个时刻的明确表示。创建NSDate之后,可以根据应用程序的需要对其进行格式化,设置样式或将其转换为日期组件。

答案 1 :(得分:9)

要将字符串放入NSDate,您可以使用NSDateFormatter,如下所示:

NSString *myDateAsAStringValue = @"20140621-061250"
NSDateFormatter *df = [[NSDateFormatter alloc] init];    
[df setDateFormat:@"yyyyMMdd-HHmmss"];
NSDate *myDate = [df dateFromString: myDateAsAStringValue];

您可能想阅读有关working with Date and Time

的帖子

修改

要将其解析为UTC,您必须添加以下行:

[df setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];

此外,当您使用NSLog打印它时,如果您使用相同的NSDateFormatter,您将获得输入字符串作为输出(因为您应用了解析函数的反转)。

以下是完整的代码,用于解析和获取标准格式的输出:

//The input
NSString *myDateAsAStringValue = @"20140621-061250";

//create the formatter for parsing
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
[df setDateFormat:@"yyyyMMdd-HHmmss"];

//parsing the string and converting it to NSDate
NSDate *myDate = [df dateFromString: myDateAsAStringValue];

//create the formatter for the output
NSDateFormatter *out_df = [[NSDateFormatter alloc] init];
[out_df setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssz"];

//output the date
NSLog(@"the date is %@",[out_df stringFromDate:myDate]);

答案 2 :(得分:8)

使用NSDate扩展的 Swift 中的一个可能解决方案(也许它可以帮助未来的观众查看此问题):

import UIKit

// For your personal information: NSDate() initializer 
// always returns a date in UTC, no matter the time zone specified.
extension NSDate {
    // Convert UTC (or GMT) to local time
    func toLocalTime() -> NSDate {
        let timezone: NSTimeZone = NSTimeZone.localTimeZone()
        let seconds: NSTimeInterval = NSTimeInterval(timezone.secondsFromGMTForDate(self))
        return NSDate(timeInterval: seconds, sinceDate: self)
    }

    // Convert local time to UTC (or GMT)
    func toGlobalTime() -> NSDate {
        let timezone: NSTimeZone = NSTimeZone.localTimeZone()
        let seconds: NSTimeInterval = -NSTimeInterval(timezone.secondsFromGMTForDate(self))
        return NSDate(timeInterval: seconds, sinceDate: self)
    }
}