安卓国际化开发中的时区问题之——夏令时,冬令时

本文探讨了安卓应用在处理时区问题时遇到的夏令时和冬令时挑战,介绍了国际时区规定,如GMT、UTC和PST。讲述了由于夏令时导致的23小时或25小时现象,并分享了项目中因时区问题引发的bug,最终提出了解决跨时区、夏令时转换问题的关键代码修改。

在说时区问题的时候,估计很多人都很不屑。因为获取时区的方法真的太简单了。尤其是很多面向百度编程的iter。

比如,获取时区的方法一句就能搞定:


        String timeZone =“GMT”+String.valueOf(TimeZone.getDefault().getRawOffset() / (3600 * 1000));

 

当时很不屑这个问题的时候。我就知道你肯定会犯的几个你自己都可能不知道的错。就是关于夏时令和冬时令的问题。

那么再说这个问题之前,我们先说说国际上对于时区的规定

时区

1884年在华盛顿召开的国际经度会议(又称国际子午线会议)上,规定将全球划分为24个时区(东、西各12个时区)。

如下图所示:

 

全球同一时刻不同时区的本地时间不同例如中国时间:10:00 AM

对于美国西部时间:18:00 PM(冬令时)

 17:00 PM(夏令时)

1. GMT VS UTC

GMT 全称 Greenwich Mean Time,中文为格林威治标准时间。

UTC 全称 Universal Time Coordinated, 中文为协调世界时。

GMTUTC都是代表0零时区的时间,两者相等。UTC1972年之后引入的概念,是GMT的后继,现广泛应用于科技领域。

2. PST

全球分为24个时区之后,从UTC/GMT 开始往西依次表示为UTC/GMT - 1-2……,往东表示为UGC/GMT+1+2……

除了UTC/GMT之外,还有一个很常见的时区:PST

PST 全称 Pacific Standard Time,太平洋标准时间,等同于UTC/GMT -8,既西八区,被北美国家使用。

冬令时、夏令时

地球自转方向从西向东,所以东边更早看到新一天的太阳。各地区在时区概念的基础上,时间更接近于太阳时(最简单的理解就是太阳直射时,当地时间基本接近12点)。

昼夜长短会随着四季变换,出于减少能源消耗的目的,提出了冬令时、夏令时的概念。

在天亮早的夏季人为将时间提前一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。

冬令时通常代表使用当地的标准时间,夏令时实施期间时钟拨快一小时,相当于时区往前(东)进一个。

每年会对时间进行两次调整,如下图所示:

 

 

也就是说,地球上并不是每一天都是24小时的。也有一天23小时或25小时的存在。

夏令时起始和结束的两天,其中开始的一天23小时,结束的一天25小时

具体好奇的可以进入这个传送门看看究竟。博主在这里就不再具体讲夏令时和冬令时的问题了。小饼干就把项目中遇到的坑跟大家分享一下:

我其中的一个项目主要服务欧美客户,春天,因为时区问题,被报了bug(美国市场部同事报的),我检查了代码,然后没发现有问题,但还是改了。然后同年冬天,再次因为这个问题被报了bug。我很郁闷,这个问题明明解决过,并且验证过的啊。为什么又出现了。然后我始终找不到我具体哪里出问题了。后来,我很奇怪美国时间为什么不对(因为办公室之前所在地之前相差18个小时,后来相差17个小时)。美国人不知道中国时区不分夏令时和冬令时(备注俄罗斯也不再区分夏令时和冬令时,但是目前国际上仍然有超过110个国家和地区区分夏令时和冬令时)。然后我就查阅了资料,明白了夏令时和冬令时的问题。

好了,故事就讲到这里,我们说说怎么解决这个问题吧。我也曾面向百度编程,查阅了这方面的资料,试过其他踩过坑的大佬写的方法,但是最后都不能达到随意切换时区和时令都测试通过的结果。(大家可以自行百度尝试其他方法和各种时区切换和时令切换测试)。

最后只能靠自己了。我回想为什么会出现导致时区的问题,并且一想,不管系统的时间怎么变,他都在相应时区内变化。一旦超过,就自动出现时区也不对了。所以这个问题就非常简单了。只需改一个地方就解决:

public static String getTimeZone() {

        String timezone;

//  这里注释的是之前获取到的时区,但是不分夏令时和冬令时(格林威治时间划分的)

//        int _t = TimeZone.getDefault().getRawOffset() / (3600 * 1000);
//         改为如下,获取系统的时间并且计算出时区就可以了

        int _t = TimeZone.getDefault().getOffset(System.currentTimeMillis()) / (3600 * 1000);

        timezone = String.valueOf(_t);


            timezone = "GMT" + timezone;



        return timezone;

    }

 

好了,这样就解决了同一个时区,因为夏天和冬天,不在同一个时区的问题。就解决了不管怎么切换时区,都能拿到改时间应该所在的时区的问题了。

### 夏令时冬令时的时间调整策略 夏令时(Daylight Saving Time,DST)是一种人为调整时间的制度,目的是为了更有效地利用日光资源。在夏令时期间,时钟通常向前调整1小时,使傍晚的日光时间延长;而冬令时则是在非夏季期间使用的标准时间,通常在夏令时结束后将时钟回调1小时[^1]。 夏令时的调整策略包括以下关键点: - **开始时间**:通常在春季的某个日期(如3月的第二个星期日)将时钟向前调整1小时。 - **结束时间**:通常在秋季的某个日期(如11月的第一个星期日)将时钟回调1小时。 - **具体时间点**:调整通常发生在午夜前后,以减少对日常活动的影响,例如凌晨2点变为3点或1点。 例如,美国的夏令时从2023年3月12日开始,凌晨2点调整为3点;从2023年11月5日结束,凌晨2点调整为1点。这种调整方式使得夏季的傍晚更晚日落,从而减少照明需求。 冬令时则是指在非夏令时期间使用的标准时间。例如,欧洲的冬令时从10月的最后一个星期日开始,到次年3月的最后一个星期日结束。在此期间,使用的是标准时间,如中欧时间(CET, UTC+1)或格林威治标准时间(GMT, UTC+0)。 ### 举例说明 以美国东部时间(Eastern Time, ET)为例: - **夏令时**:从3月的第二个星期日开始,东部时间(ET)变为东部夏令时(EDT, UTC-4)。 - **冬令时**:从11月的第一个星期日开始,东部夏令时(EDT)变回东部标准时间(EST, UTC-5)。 以下是一个简单的Python示例,展示如何使用`pytz`库处理夏令时冬令时的转换: ```python from datetime import datetime import pytz # 创建一个纽约时区的时间对象(纽约使用夏令时) ny_tz = pytz.timezone('America/New_York') # 创建一个日期时间对象 dt = datetime(2023, 3, 12, 2, 30) # 2023年3月12日凌晨2:30 # 将日期时间对象绑定到纽约时区 ny_time = ny_tz.localize(dt) print("夏令时开始时间:", ny_time) # 创建一个日期时间对象,表示夏令时结束时间 dt_end = datetime(2023, 11, 5, 1, 30) # 2023年11月5日凌晨1:30 ny_time_end = ny_tz.localize(dt_end) print("夏令时结束时间:", ny_time_end) # 转换为UTC时间 utc_time = ny_time.astimezone(pytz.utc) print("对应的UTC时间:", utc_time) ``` ### 注意事项 - 夏令时的调整规则因国家和地区而异,某些地区可能不实行夏令时。 - 夏令时的开始和结束日期可能每年不同,需参考具体年份的官方公告。 - 使用支持时区数据库的库(如`pytz`)可以避免手动计算时区偏移量带来的误差。 ###
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值