iOS 时间戳在不同时区转换问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS 时间戳在不同时区转换问题相关的知识,希望对你有一定的参考价值。

参考技术A 一、给定一个10位时间戳,转成不同时区的日期

//给定一个时间戳

NSString *test = @"1652861974”;

//转成北京时区下的日期

NSDateFormatter *beijingFormatter = [[NSDateFormatter alloc] init];

[beijingFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

NSTimeZone *beijingZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT+0800"];

[beijingFormatter setTimeZone:beijingZone];

//转成手机系统设置的时区(纽约)下的日期

NSDateFormatter *localFormatter = [[NSDateFormatter alloc] init];

[localFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

NSTimeZone *localZone = [NSTimeZone systemTimeZone];//当前手机设置的是纽约时区

[localFormatter setTimeZone:localZone];

 NSDate* testDate = [NSDate dateWithTimeIntervalSince1970:[test longLongValue]];

NSString* beijingDateString = [beijingFormatter stringFromDate: testDate];//北京时区下的日期字符串 :“2022-05-18 16:19:34”

NSString* localTimeString = [localFormatter stringFromDate: testDate];// 换成本地(纽约)时间:2022-05-18 04:19:34

NSLog(@"服务器返回北京时间:%@ 转换成本地时区时间:%@ ", beijingDateString, localTimeString);

结果打印: 服务器返回北京时间:2022-05-18 16:19:34 转换成本地时区时间:2022-05-18 04:19:34

二、反向验证同一时刻下世界在不同时区的日期返回的时间戳是相同的:

北京时区日期: 2022-05-18 16:19:34 ( 以上的beijingDateString对应的 )

纽约时区日期: 2022-05-18 04:19:34( 以上的localTimeString对应的 )

NSDate *beiDate = [beijingFormatter dateFromString: beijingDateString];

NSTimeIntervalbeiInterval = [beiDate   timeIntervalSince1970];

NSDate*LocDate = [localFormatter   dateFromString: localTimeString];

NSTimeIntervalLocInterval = [LocDate  timeIntervalSince1970];

NSLog(@"原始时间戳:%@ 北京时区生成时间戳:%f  本地时区生成时间戳:%f ",test,( double )beiInterval,( double ) LocInterval);

结果打印:  原始时间戳:1652861974  北京时区生成时间戳:1652861974.000000   本地时区生成时间戳:1652861974.000000 

验证了同一时刻虽然处于世界不同时区,但是拿到的时间戳是一样的,前提是转成对应时区下的日期即 NSDateFormatter要设置对应的时区。

为啥 PHP 和 MySQL 的 unix 时间戳在 1983 年 10 月 29 日不同?

【中文标题】为啥 PHP 和 MySQL 的 unix 时间戳在 1983 年 10 月 29 日不同?【英文标题】:Why do PHP and MySQL unix timestamps diverge on 1983-10-29?为什么 PHP 和 MySQL 的 unix 时间戳在 1983 年 10 月 29 日不同? 【发布时间】:2011-09-07 03:04:21 【问题描述】:

我一直在我的应用程序中使用 PHP 的 strtotime 和 MySQL 的 UNIX_TIMESTAMP 函数,将日期转换为时间戳。 PHP 和 MySQL 在我的本地机器上运行,这些函数通常返回相同的结果,正如我所期望的那样:

$ php
<?php echo strtotime("2011-06-02"); ?>
1307001600

mysql> SELECT UNIX_TIMESTAMP("2011-06-02") ts;
+------------+
| ts         |
+------------+
| 1307001600 |
+------------+

但是,我碰巧注意到,当我输入1983-01-01 作为日期时,结果不再相等:

$ php
<?php echo strtotime("1983-01-01"); ?>
410263200

mysql> SELECT UNIX_TIMESTAMP("1983-01-01") ts;
+-----------+
| ts        |
+-----------+
| 410256000 |
+-----------+

如您所见,PHP 返回 410263200,而 MySQL 返回 410256000 - 相差 7200 秒。

这让我很好奇,我想知道时间戳在哪一天不再等价,所以我写了一个小程序,从今天的日期开始(以 Ymd 格式),使用 PHP 的 strtotime 和 MySQL 的 UNIX_TIMESTAMP并比较结果。然后它从每个值中减去 1 天并循环,直到它们不再相等。

结果:

1983-10-29

1983 年 10 月 29 日,出于某种原因,strtotimeUNIX_TIMESTAMP 返回的值相差 7200 秒。

有什么想法吗?

感谢阅读。

【问题讨论】:

你在哪个时区? (date_default_timezone_get())?想知道这是否是特定于时区的一些奇怪的日历变化——大概发生在 1983 年 10 月 30 日。 两个小时,世界停止了,所以我们都可以在新发布的“亚当”上玩我们的 ColecoVision 游戏 【参考方案1】:

你说你是在阿拉斯加时间。来自http://www.statoids.com/tus.html:

1983-10-30 02:00:除阿留申群岛和圣劳伦斯岛外,阿拉斯加的所有地区都切换到 AT。在改变之前,阿拉斯加以西 138°(朱诺)以东一直在 PT 上; 138°W 和 141°W(Yakutat)之间的时间是育空时间,即 UTC-9 和 DST; 162°W(Nome)以西一直在白令时间,这是 UTC-11 与 DST。阿拉斯加-夏威夷区域名称更改为夏威夷-阿留申。

所以,我猜这是因为您的时区在 1983 年 10 月 30 日改变了两个小时(7200 秒 = 2 小时)。

我猜 MySQL 的 UNIX_TIMESTAMP 使用的时区与 PHP 中的阿拉斯加设置不同,这可能是服务器默认设置,也可能取决于您的连接设置,因此当您到达该日期时,它们会出现差异。

您可以通过询问 MySQL 在与SELECT @@global.time_zone, @@session.time_zone; 的连接上的时区设置是什么来收集更多信息;请参阅this answer 了解有关输出的更多信息以及如何解释它。

【讨论】:

不错的发现...所以报告准确。 也是一个不错的read 特别是因为它记录了在 1883 年(100 年前)为美国设定了时区,除了阿拉斯加,因为它没有铁路。 是的。我猜 MySQL 的 UNIX_TIMESTAMP 使用的是不同的时区,这可能是服务器默认时区,或者取决于您的连接设置,因此当您到达转换日期时,这与 PHP 的阿拉斯加时区不同。 @echo 不用担心 :) 好问题! MySQL 为这两个值返回 SYSTEM,PHP 报告 US/Alaska。日期和时间首选项 (OSX) 表示 AKDT。

以上是关于iOS 时间戳在不同时区转换问题的主要内容,如果未能解决你的问题,请参考以下文章

Hive 时间操作

如何根据 Big Query 中的 UTC 时间戳在 Data Studio 中显示本地时区的日期/时间

为啥 PHP 和 MySQL 的 unix 时间戳在 1983 年 10 月 29 日不同?

不同时区转换时间戳

没有时区的时间戳中的夏令时时间偏移

跪求啊 时间戳在jsp页面上怎么转换为yyyy-MM-dd HH:mm:ss