时区概念
众所周知,地球是球状体,白天与黑夜的形成是因为地球的自转导致,所以,同一个时刻,不同地区的人们所处的白天与黑夜并不同,但是,每个地区的人们从生活便利程度出发,都将本地时间与日出日落时间联系在一起,比如当美国人说早上5点,与中国人说早上5点,所指的都是本地的早上某一刻,但是放到全球,当美国人说早上5点的时候,中国人这时候处在下午6点。
时间不统一,就带来很多混乱,为了改变这种状况,国际上就制定了世界标准时机制。
1884年在华盛顿召开的一次国际经度会议(又称国际子午线会议)上,规定将全球划分为24个时区(东、西各12个时区)。
如图,每个时区跨经度(东西为经,南北为纬)15度,东西时区以东西180度为界, 每个时区之间相差1小时,越往东,时间越早(地球是由西往东转,所以太阳是东升西落),所以美国人看到太阳的时候,我们其实是在他们的昨天下午。
有的国家国土很大,一个时区可能放不下,可能会有几个时区,比如美国分4个时区,有的为了国家管理方便,即使跨几个时区也会把不同时区的地区人为指定使用某一时区时间,比如中国,全中国只使用东八区,俗称北京时间。
在linux中,时区一般会选择一个代表性城市命名,但是这个北京时间你在时区名称里找不到,只有Asia/Shanghai(上海时区)。因为时区这套东西是外国人制定的,上海作为一个长期殖民城市,外国人更熟悉上海,其实香港,澳门、台湾也有自己的城市命名时区:Asia/Hongkong, Asia/Macau, Asia/Taibei。大陆还有其他几个:Asia/Kashgar(喀什), Asia/Urumqi(乌鲁木齐),Asia/Chongqing(重庆),Asia/Harbin(哈尔滨)
如果你很在意为什么不使用自己的家乡作为时区名,可以参照这里
时区与经度对照表
utc - Coordinated Universal Time,即世界标准时间、协调世界时
utc+8 - 即东八区,中国所用时区,也是Asia/Shanghai所代表的区域
另外还有GMT时间(格林尼治时间),GMT的时区划分与UTC是一样的,不同的是以前GMT是根据太阳高度来校正时间,而UTC是由更现代的原子钟授时,具有更高的时间精确度,因此现在使用GMT时间实际上就是使用UTC时间。
时区 |
时区范围 |
时区中心线 |
---|---|---|
UTC |
7.5°W~7.5°E |
0° |
UTC+1 |
7.5°E~22.5°E |
15°E |
UTC+2 |
22.5°E~37.5°E |
30°E |
UTC+3 |
37.5°E~52.5°E |
45°E |
UTC+4 |
52.5°E~67.5°E |
60°E |
UTC+5 |
67.5°E~82.5°E |
75°E |
UTC+6 |
82.5°E~97.5°E |
90°E |
UTC+7 |
97.5°E~112.5°E |
105°E |
UTC+8 |
112.5°E~127.5°E |
120°E |
UTC+9 |
127.5°E~142.5°E |
135°E |
UTC+10 |
142.5°E~157.5°E |
150°E |
UTC+11 |
157.5°E~172.5°E |
165°E |
东西十二区 |
172.5°E~172.5°W |
180° |
UTC-11 |
172.5°W~157.5°W |
165°W |
UTC-10 |
157.5°W~142.5°W |
150°W |
UTC-9 |
142.5°W~127.5°W |
135°W |
UTC-8 |
127.5°W~112.5°W |
120°W |
UTC-7 |
112.5°W~97.5°W |
105°W |
UTC-6 |
97.5°W~82.5°W |
90°W |
UTC-5 |
82.5°W~67.5°W |
75°W |
UTC-4 |
67.5°W~52.5°W |
60°W |
UTC-3 |
52.5°W~37.5°W |
45°W |
UTC-2 |
37.5°W~22.5°W |
30°W |
UTC-1 |
22.5°W~7.5°W |
15°W |
导入时区对象
from datetime import tzinfo
tzinfo对象的方法
方法名 | 描述 |
dst | 返回一个timedelta对象,代表夏令时调整,如果没有夏令时,返回None,中国已经取消夏令时制度 |
fromutc | 将一个utc时间转换为本地时间,并返回新的datetime对象,该方法由datetime对象的astimezone调用。此方法已经提供了默认实现,无需重新定义此方法。 |
tzname(dt) | 返回代表时区名称的字符串,dt可以为一个日期时间对象或者None |
utcoffset | 使用timedelta对象表示与utc的差值,负值为utc以西 |
tzinfo子类定义示例
from datetime import tzinfo, timedelta, datetime
ZERO = timedelta(0)
HOUR = timedelta(hours=1)
SECOND = timedelta(seconds=1)
import time as _time
# 标准时间差
STDOFFSET = timedelta(seconds = -_time.timezone)
# 是否夏令时,考虑夏令时因素计算时差
if _time.daylight:
# 是
DSTOFFSET = timedelta(seconds = -_time.altzone)
else:
# 否
DSTOFFSET = STDOFFSET
DSTDIFF = DSTOFFSET - STDOFFSET
class LocalTimezone(tzinfo):
def fromutc(self, dt):
assert dt.tzinfo is self
stamp = (dt - datetime(1970, 1, 1, tzinfo=self)) //获得时间戳
args = _time.localtime(stamp)[:6] //转换为本地时间的年月日时分秒
dst_diff = DSTDIFF // SECOND
# Detect fold
fold = (args == _time.localtime(stamp - dst_diff))
return datetime(*args, microsecond=dt.microsecond,
tzinfo=self, fold=fold)
def utcoffset(self, dt):
if self._isdst(dt):
return DSTOFFSET
else:
return STDOFFSET
def dst(self, dt):
if self._isdst(dt):
return DSTDIFF
else:
return ZERO
def tzname(self, dt):
return _time.tzname[self._isdst(dt)]
def _isdst(self, dt):
tt = (dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.weekday(), 0, 0)
stamp = _time.mktime(tt)
tt = _time.localtime(stamp)
return tt.tm_isdst > 0
Local = LocalTimezone()
讨论区