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 日,出于某种原因,strtotime
和 UNIX_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 时间戳在不同时区转换问题的主要内容,如果未能解决你的问题,请参考以下文章
如何根据 Big Query 中的 UTC 时间戳在 Data Studio 中显示本地时区的日期/时间