无法正确格式化时间

Can't format time right

我有以下方法将给定时间(UTC 格式)作为参数并将其转换为当前时间,比方说 'friendlier format'。

A​​ valid/normal 输入可能是:'11:30' 或 '1:30' 我的问题是虽然我设备中设置的时区是纽约(-4 GMT) 甚至在此示例中进行硬编码!此函数不断将时间转换为格林威治标准时间 -5 (分别为上午 6:30 和下午 8:30)

-(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]

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

当您仅解析没有日期的时间时,返回的日期将为 Jan 1, 2000。由于夏令时,今天您与 GMT 之间的时差可能与 1 月 1 日不同。您需要在代码中间添加一些额外的步骤以使其执行正确的操作。

我对 Objective-C 真的很生疏,所以我将总结一下您需要执行的步骤。我还可以 post swift 中的解决方案,您认为这会有所帮助,因为它基本上相同,只是语法不同。

  1. 保留从字符串
  2. 创建 date 的代码
  3. 创建一个 Calendar 并将其时区设置为 GMT
  4. 创建一个 DateComponents 包含当前日期的年、月、日
  5. 创建一个 DateComponents,其中包含从 date
  6. 起的小时、分钟
  7. 将两个 DateComponents 合并在一起,编辑其中一个或制作一个新的
  8. 使用日历从组件中获取日期
  9. 使用您的 dateFormatInputOutput 格式化程序从这个日期创建一个字符串

问题是纽约是晚 4 小时还是 5 小时 GMT/UTC 取决于您当前是否处于夏令时。我们目前处于“夏令时”时间,但在没有相反信息的情况下,日期格式化程序将假定日期为 2000 年 1 月 1 日,这不是夏令时。因此断开连接。

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

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

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

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


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

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

具体来说,如果用户将他们的设备配置为 24 小时时钟,则以上内容将遵循用户指示的任何内容,而不是强制采用他们可能不喜欢的格式。

另请注意,您不必强制设置时区或区域设置(除非您真的打算将其强制设置为纽约,即使用户在加利福尼亚州也是如此),因为它也将默认为用户设备的设置.这仅取决于您是否真的想将其强制为东部时区。


如果您从网络服务中读取 date/time 字符串,您可能还需要根据 Technical Note 1480 指定一致的语言环境。从技术上讲,它是一个 time-only 字符串,可能不需要,但这是一个很好的做法:

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