无法正确格式化时间

时间:2019-05-15 14:47:10

标签: objective-c time nsdateformatter datetime-conversion

我有以下方法,它以给定的时间(以UTC为单位)作为参数,并以“更友好的格式”将其转换为当前时间。

有效/正常输入可能是:“ 11:30”或“ 1:30” 。我的问题是,尽管设备中设置的时区是纽约(-4 GMT)甚至硬编码在这个例子中!此功能会持续将时间转换为-5 GMT (分别为6:30 AM和8:30 PM)

-(NSString*) convertServerTimeToAppTimeFormat:(NSString*) input {
NSDateFormatter *dateFormatInput = [[NSDateFormatter alloc] init];
[dateFormatInput setDateFormat:@"HH:mm"];
[dateFormatInput setTimeZone :[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate *date = [dateFormatInput dateFromString:input];

NSDateFormatter *dateFormatInputOutput = [[NSDateFormatter alloc] init];
[dateFormatInputOutput setDateFormat:@"h:mm a"];
[dateFormatInputOutput setTimeZone: [NSTimeZone localTimeZone]];
[dateFormatInputOutput setTimeZone:[NSTimeZone timeZoneWithName:@"America/New_York"]];
return  [dateFormatInputOutput stringFromDate:date];
}

肯定有一些我看不到的非常明显的东西。我通常会使用:

[NSTimeZone localTimeZone]

要获得用户所在的当前时区,而不是像我在此处那样对其进行硬编码,但是我认为硬编码版本应有助于使该错误更加明显。

2 个答案:

答案 0 :(得分:2)

仅分析没有日期的时间时,重新调整的日期将为Jan 1, 2000。由于夏时制的原因,今天您和GMT之间的偏移量可能与1月1日的偏移量有所不同。您需要在代码中间添加一些额外的步骤,以使其执行正确的操作。

我对Objective-C真的很生疏,所以我只总结您需要做的步骤。我也可以迅速发布该解决方案,因为它基本上是相同的,只是语法不同,所以对您有所帮助。

  1. 保留从字符串创建date的代码
  2. 创建一个时区设置为Calendar的{​​{1}}
  3. 创建一个GMT,其中包含当前日期的年,月,日
  4. 创建一个{@ {1}}开始的DateComponents
  5. 将两个DateComponents合并在一起,然后编辑其中一个或新建一个
  6. 使用日历从组件中获取日期
  7. 使用您的date格式器从该日期开始创建一个字符串

答案 1 :(得分:2)

问题在于,纽约州比格林尼治标准时间/世界标准时间晚4或5小时取决于您当前是否处于夏令时。我们目前处于“夏令时”时间,但是在没有相反信息的情况下,日期格式器将假定为2000年1月1日,而不是夏令时。因此断开连接。

但是您可以将格式化程序的defaultDate设置为今天:

NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]];
[dateFormatInput setDefaultDate:today];

以上将格式化程序默认为今天的日期。显然,如果您的输入有一个单独的字段来标识与此时间相关的日期,请使用该字段。

但是通过设置defaultDate,将使仅时间字符串知道是否应应用夏令时,从而产生所需的时区转换。


顺便说一句,我建议不要对输出字符串使用dateFormat。指定timeStyle,它将根据用户设备的设置对其进行适当的格式化:

NSDateFormatter *dateFormatInputOutput = [[NSDateFormatter alloc] init];
[dateFormatInputOutput setTimeStyle:NSDateFormatterShortStyle];
return [dateFormatInputOutput stringFromDate:date];

具体来说,如果用户将其设备配置为24小时制,则上面的内容将兑现用户指示的内容,而不是强制采用他们不喜欢的格式。

还请注意,您不必强制设置时区或区域设置(除非您确实要强制将其设置为NY(即使用户位于CA内也是如此)),因为它也将默认为用户设备的设置。这仅取决于您是否真的想将其强制到东部时区。


如果您要从网络服务中读取日期/时间字符串,则可能还想根据Technical Note 1480指定一致的语言环境。从技术上讲,它是一个仅用于时间的字符串,可能不需要,但这是一个好习惯:

[dateFormatInput setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]];