日期/时间的国际化,不只涉及到地理位置(Locale,好比星期、月份等日历本地化表示),还涉及到时区(TimeZone,针对UTC/GMT的偏移量)。时区不只是地理位置规定,更是政治规定,好比中国从地理位置上跨5个时区,但只使用一个统一时区(id=Shanghai/Asia)。 javascript
优先使用用户确认的locale/timezone/format。不然使用应用系统默认,必须显示时区,好比amazon的限时销售显示为PST时区。 html
DateFormat df = new SimpleDateFormat(pattern, userLocale);
df.setTimeZone(userTimeZone);
Date userInputDate = df.parse(inputDate);
同一服务系统内全部主机的操做系统、数据库、JVM,原则上应该使用相同时区。 java
同一服务系统跨时区服务的,日期/时间数据必须带有时区信息。服务系统之间交换日期/时间数据的,必须带有时区信息。 mysql
同一服务系统内,数据库服务器按照其服务的地理位置和时区设置,应用服务器参照数据库服务器设置。数据库软件系统和JVM默认时区不作调整,均采用主机操做系统时区。 web
全部主机开启NTP,应用服务器向数据库服务器请求时间同步。 spring
字段类型 |
字节 |
精度 |
范围 |
说明 |
---|---|---|---|---|
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' | 时间值或持续时间 |
说明: sql
字段类型 | 字节 |
精度 |
范围 |
说明 |
---|---|---|---|---|
date |
7 |
秒 |
-4712-01-01 00:00:00 to 9999-12-31 23:59:59 | 日期和时间混合 |
timestamp(n) | 7-11 | 秒~纳秒 |
秒范围同上 | 日期和时间混合,小数秒位数(0-9,至关于秒-纳秒)可设置 |
timestamp WITH TIME ZONE | 9-13 |
秒~纳秒 | 秒范围同上 | 日期和时间混合,同时存储时区。若输入不指定时区,则使用数据库时区 |
timestamp WITH LOCAL TIME ZONE | 7-11 | 秒~纳秒 | 秒范围同上 | 转换为数据库时区后存储,不存储时区 |
interval year to month | 5 | N/A | N/A | 存储年或月指定的时间段 |
interval day to second | 11 |
N/A | N/A |
存储天,小时,分钟,秒指定的时间段 |
说明: 数据库
字段类型 | 字节 | 精度 |
范围 |
说明 |
---|---|---|---|---|
smalldatetime | 4 |
分 |
1900-01-1 00:00:00 to 2079-06-06 23:59:00 | 日期和时间混合 |
datetime | 8 | 3.33毫秒 |
1753-01-01 00:00:00.000 to 9999-12-31 23:59:59.998 | 日期和时间混合 |
datetime2(n) | 6-8 | 100ns | 0001-01-01 00:00:00.0000000 to 9999-12-31 23:59:59.9999999 | 日期和时间混合。n为小数秒精度,取值范围为0-7,表示1秒-100ns |
date | 3 | 天 |
001-01-01 to 9999-12-31 | 日期 |
time(n) | 3-5 | 100ns | 00:00:00.0000000 to 23:59:59.9999999 | 时间。n为小数秒精度,取值范围为0-7,表示1秒-100ns |
datetimeoffset | 8-10 |
100ns | 0001-01-01 00:00:00.0000000 to 9999-12-31 23:59:59.9999999 | 日期和时间混合。n为小数秒精度,取值范围为0-7,表示1秒-100ns。 数据库时区与UTC的时区偏移量(精确到分钟)被存储。 |
jdbc使用java.util.Date的三个子类(见上图),负责与数据库系统交互。java.sql.Date只包含日期,java.sql.Time只包含时间,java.sql.Timestamp包含日期和时间混合,精确到纳秒。java type, jdbc sql type和数据库字段类型对应关系以下: apache
java.sql |
java.sql.Types |
mysql |
sqlserver |
oracle |
---|---|---|---|---|
Date |
DATE |
date |
date |
date |
Time |
TIME |
time |
time |
date |
Timestamp |
TIMESTAMP |
datetime timestamp |
datetime datetime2 datetimeoffset |
date timestamp [with ....] |
String |
VARCHAR | timestamp WITH TIME ZONE |
当检索列时,返回给用户的值被转换成 TIME_ZONE 会话参数指定的时区(JVM报告的当前时区:TimeZone.getDefault(),来自-Duser.timezone的设定或主机操做系统时区,或设置TimeZone.setDefault(timezone))。 json
当设置列时(PreparedStatement.setTimestamp):设置的值将被转换成 TIME_ZONE 会话参数指定的时区。
mybatis关于日期/时间处理的地方,主要是使用TypeHandler:
register(Date.class, new DateTypeHandler()); register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler()); register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler()); register(JdbcType.TIMESTAMP, new DateTypeHandler()); register(JdbcType.DATE, new DateOnlyTypeHandler()); register(JdbcType.TIME, new TimeOnlyTypeHandler()); register(java.sql.Date.class, new SqlDateTypeHandler()); register(java.sql.Time.class, new SqlTimeTypeHandler()); register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());
各个TypeHandler主要处理java.util.Date类型和jdbc sql type的映射关系和转换,屏蔽java.sql.Date/Time/Timestamp的差别。好比:
<resultMap ... > <result column="createTime" property="createTime" jdbcType="TIMESTAMP" /> </resultMap> <select ...> select ... from ... where ... <![CDATA[ and createTime>= #{start,jdbcType=TIMESTAMP} and createTime<#{end,jdbcType=TIMESTAMP} ]]> </select>
struts2/spring3 mvc针对日期/时间处理和国际化方面,主要涉及到拦截器设置locale上下文环境、日期/时间字符串输入解析、验证、国际化显示这几个方面。
二者均将获取到的locale暴露到request scope context中,供解析、国际化使用。二者均缺少TimeZone相关的拦截器。若是单点登陆系统增长了用户profile管理,则还能够增长基于profile的拦截器实现。
两个框架都利用DateFormat的parse方法进行解析,支持locale/timezone转换。
在没法获知用户locale/timezone的状况下,或者用户输入格式随意,经过猜想来解析用户的时间含义,是不够准确的。spring框架把这个决定权交给开发者,很明智。所以,在涉及到用户输入时,必须明确规范用户的输入格式、协商用户时区。
在输入解析时进行了日期/时间格式合法性验证后,二者的验证框架,均有针对日期/时间的能否为空、范围验证。
都可以在二者支持的模板系统中添加相关的宏或tag。实际格式化由暴露在view context中的DateFormat帮助类,根据request scope context中的locale/timezone或缺省设置来处理。
xml/json也被MVC框架用来做为视图层。更多的时候,用做两个系统进行信息交互(好比webservice和rest)的一种中间格式。
JAXB规范中的日期/时间格式,遵循XML中的日期/时间规范(ISO8601),JDK内部实现中格式以下:
JSON规范并无定义如何序列化日期时间。json框架主要处理方式以下: