日期/时间的国际化,不仅涉及到地理位置(Locale,比如星期、月份等日历本地化表示),还涉及到时区(TimeZone,针对UTC/GMT的偏移量)。时区不仅是地理位置规定,更是政治规定,比如中国从地理位置上跨5个时区,但只使用一个统一时区(id=Shanghai/Asia)。
用户locale/timezone的获取
猜测:根据IP、HTTP Header(Accept-Language),js脚本等方式猜测,不准确。
客户请求参数。有一个入口让用户选择locale/timezone,同时也可让用户选择date/time format偏好。常见于后台管理系统。
用户locale/timezone的存储
cookie
用户profile管理系统
客户端输出
优先使用用户确认的locale/timezone/format。否则使用应用系统默认,必须显示时区,比如amazon的限时销售显示为PST时区。
客户端输入
相对时间:比如一周内,1天前等。直接转换为应用系统相对时间。
绝对时间:允许客户端输入具体日期/时间的系统,有用户确认timezone的,需转换为应用系统默认timezone再处理。比如:
DateFormat df = new SimpleDateFormat(pattern, userLocale);
df.setTimeZone(userTimeZone);
Date userInputDate = df.parse(inputDate);
服务系统时区
同一服务系统内所有主机的操作系统、数据库、JVM,原则上应该使用相同时区。
系统交互
同一服务系统跨时区服务的,日期/时间数据必须带有时区信息。服务系统之间交换日期/时间数据的,必须带有时区信息。
操作系统时区设定
同一服务系统内,数据库服务器按照其服务的地理位置和时区设置,应用服务器参照数据库服务器设置。数据库软件系统和JVM默认时区不做调整,均采用主机操作系统时区。
所有主机开启NTP,应用服务器向数据库服务器请求时间同步。
数据库日期/时间字段类型存储
mysql(5.5)
字段类型
字节
精度
范围
说明
date
3
天
'1000-01-01' to '9999-12-31'
日期
datetime
8
秒
'1000-01-01 00:00:00' to '9999-12-31 23:59:59'
日期和时间混合
timestamp
4
秒
'1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC.
日期和时间混合,转换为UTC时区的时间后存储;insert/update时,由数据库自动更新。
year
1
年
1901 to 2155, or 0000
年份
time
3
秒
'-838:59:59' to '838:59:59'
时间值或持续时间
说明:
datetime/timestamp可接受微妙级的时间,但是存储时只保留到秒级别。需要存储毫秒级别的,可以使用bigint类型字段,在应用程序级别进行long型的epoch毫秒和Date类型转换。