处理全球化问题的重要部分,时间处理。
基础
时间戳
距离某一时刻的到现在所经过的秒数(毫秒数),通常用字符串表示。
一般取 格林威治时间 1970年01月01日00时00分00秒,即 1970-01-01 00:00:00 UTC
同一时刻,全球各时区的时间戳是一致的,并不会根据时区而变化。
时区
由于世界各地区的经度不同,地方时也有所不同,为了克服各时间上的混乱,划分时区。
1884年在华盛顿召开的国际经度会议上,规定将全球划分为24个时区,中时区(零时区)、东1-12区,西1-12区,每个时区横跨经度15度,时间正好1小时,最后东西12区,各跨经度7.5度,以东西经180度为界。
实际上,很多国家或地区都不严格按照时区来计算时间,时区的划分是为了方便沟通克服混乱,以中国为例,横跨5个时区,但一般都只用北京时间作为标准(东八区)。
GMT & UTC
GMT
- Greenwich Mean Time
- 格林威治标准时间、世界时
- GMT以地球自转运动为标准的时间计量系统
UTC
- Universal Time Cooridinated
- 协调世界时、世界统一时间、世界标准时间、国际协调时间
- UTC是以原子时秒长为基础,在时刻上尽量接近于世界时的一种时间计量系统,更加精准,广泛用在科技领域
- 原子时:物质的原子内部发射的电磁振荡频率为基准的时间计量系统
划分24时区后,东时区可表示为 GMT/UTC +1, GMT/UTC +2 …,西时区可表示为 GMT/UTC -1, GMT/UTC -2 …
夏令时 & 冬令时
出于种种原因,推行一种时间机制,在一年的某个时间开始,把时间调快一个小时,某个时间之后,再把时间调慢一个小时。
将时间调快后到下次调慢前的这段时间,称为夏令时;以此衍生出冬令时概念,就是与夏令时对应,其实可以理解为正常的时间。
这种方式的好处,据说节能减排等,没感觉到,但是弊端,计时混乱却显而易见,中国曾在1986年至1991年实行过,后面就不再实行了。
不管是夏令时还是所谓的冬令时,最大的问题是在于 时间调快 和 时间调慢 的那两个时间点;正常两天的时间间隔是 86400 秒,但是时间被调整的那天时间间隔将变成 82800 秒 和 90000 秒。
以时区 UTC -5 东部时间(美国和加拿大)为例,时间戳与对应日期如下
2022-03-11 06:00:00 1646996400
2022-03-12 06:00:00 1647082800
2022-03-13 06:00:00 1647165600
2022-03-14 06:00:00 1647252000
2022-11-05 06:00:00 1667642400
2022-11-06 06:00:00 1667732400
2022-11-07 06:00:00 1667818800
2022年3月12日到2022年3月13日 6点,时间戳间隔是 82800 秒
2022年11月5日到2022年11月6日 6点,时间戳间隔是 90000 秒
实践
lua时间方法
lua中主要有这几种方法来做时间相关转换
- os.time
- os.date
os.time([table])
- return: string
- 时间戳字符串
- param: table
- [可选参数] table
- 若不传参数,则返回当前时间时间戳;若传参,返回参数指定时间(年月日时分秒及是否夏令时)时间戳
- table结构,必须包含字段 year、month、day,可选包含 hour(默认12)、min(默认0)、sec(默认0)、isdst(默认nil)
- [可选参数] table
1 | -- 环境:系统时区为 UTC -5 东部时间(美国加拿大) |
os.date([format [, time]])
- return: string/table
- 返回包含日期及时间的字符串或表结构
- param: string, string
- [可选参数] format, 格式
- 前缀为 ‘!’ 则代表以UTC格式化
- *t 代表返回table结构,其他则返回string结构
- 对于字符串的情况,可以预制一些参数,方便填充
- [可选参数] time, 时间戳
- 若不传,则使用当前的时间戳
- [可选参数] format, 格式
format格式符
格式符 | 含义 | 样例 |
---|---|---|
%Y | 年 | 2022 |
%y | 年(后两位数) | 22 |
%m | 月 | 2 |
%d | 日 | 20 |
%H | 时(24小时制) | 15 |
%I | 时(12小时制) | 3 |
%M | 分 | 30 |
%S | 秒 | 20 |
%x | 日期 | 03/15/22 |
%X | 时间 | 05:05:35 |
%c | 日期和时间 | 03/15/22 05:05:35 |
%P | 上午/下午 | am/pm |
%a | 星期(简写) | Fri |
%A | 星期(全写) | Friday |
%b | 月份(简写) | Sep |
%B | 月份(全写) | September |
%w | 该星期中第几天 | 2 (0-6, 周日-周六) |
%W | 该年中第几星期 | 4 |
%j | 该年中第几天 | 230 |
%% | 字符串’%’ | % |
1 | -- 环境:系统时区为 UTC -5 东部时间(美国加拿大) |
工具类
作为处理时间的工具类,要考虑几个问题
- 时间戳
- 客户端时区(本地时区)
- 服务器时区
一般来说,禁止使用本地时间进行计算,都是用服务器时间进行计算,但是在时间戳与实践转换时,不可避免受到本地时区影响,要注意将这些影响消除掉,尤其是在做全球化的游戏。
就是一旦用到Lua自带的 os.time / os.date 方法,必然会带上本地的时区去计算,所以要转换成时间戳,就需要将本地时区的影响消除。
1 | --[[ |