日期组件国际化设置时区方案

@LiuYueKai 2017-03-30 08:42:03发表于 iuap-design/blog

日期组件国际化设置时区方案

需求说明

国际化

国际化(Internationalization,英文缩写为I18N)是指软件对不同的本地语言、本地客户和编码字符集的适应能力。

日期国际化

在国际化过程中存在如下场景,全球范围内进行应用操作时对时间显示及保存都要按照公司所在时区进行处理。
比如公司所在地对应时区为+5区,公司员工所在地为+8区。

  • 日期时间处理:员工所在地时间为2017-03-28 12:00:00,则在应用操作时显示及存储时间应处理为2017-03-28 09:00:00。
  • 日期处理:员工选择日期为2017-03-28,则存储时应处理为+5区 2017-03-28 00:00:00,即+8区 2017-03-28 03:00:00。

方案说明

以下说明中都以当前机器对应时区为+8,设置的时区为+5为例。

  • 首先日期类型存储是要以日期对象getTime()获取的long值进行存储
  • 前端整个操作过程都是+5时区对应的时间,达到的效果相当于浏览器封闭环境中就是+5区。

方案实现

  • 后端查询的数据在显示时需要转化为+5区的时间
  • 无数据时打开面板默认显示+5时区的当前时间,比如+8为12:00:00,则+5为9:00:00
  • 用户选择的时间按照+5时区转化为long进行存储。

核心代码

    /**
     * 根据当前时区日期对象获取指定时区日期对象
     * @param  {Date} date     当前时区日期对象
     * @param  {number} timezone 指定时区
     * @return {Date}          转化后的日期对象
     */
    getDateByTimeZonec2z: function(date, timezone) {
        var dateObj = u.date.getDateObj(date);
        var localTime = dateObj.getTime();
        var localOffset = dateObj.getTimezoneOffset() * 60000;
        var utc = localTime + localOffset;
        var calctime = utc + (3600000 * parseFloat(timezone));
        return new Date(calctime);
    },
    /**
     * 根据指定时区日期对象获取当前时区日期对象
     * @param  {Date} date     指定时区日期对象
     * @param  {number} timezone 指定时区
     * @return {Date}          转化后的日期对象
     */
    getDateByTimeZonez2c: function(date, timezone) {
        var dateObj = u.date.getDateObj(date);
        var localTime = dateObj.getTime();
        var localOffset = dateObj.getTimezoneOffset() * 60000;
        var utc = localTime - (3600000 * parseFloat(timezone)) - localOffset;
        return new Date(utc)
    }

参数设置

  • 全局增加u_timezone用于设置时区,通过cookie设置
    • datatable的meta属性上增加timezone,日期组件增加参数timezone
    • 参数优先级:meta》组件》cookie

测试用例

测试过程中用到的时间对应的long值说明,都以+5区为准(通过+5区时间+3小时获取的日期对象对应long值)

  • 2017-03-27 11:00:00对应值为1490594400000((new Date('2017-03-27 14:00:00')).getTime())
  • 2017-03-27 15:00:00对应值为1490608800000((new Date('2017-03-27 18:00:00')).getTime())
  • 2017-03-28 00:00:00对应值为1490641200000((new Date('2017-03-28 03:00:00')).getTime())
  • 2017-03-15 00:00:00对应值为1489518000000((new Date('2017-03-15 03:00:00')).getTime())

日期时间

  • 数据库存储值为1490594400000,显示时显示为2017-03-27 11:00:00,点开面板显示时间依旧为2017-03-27 11:00:00,选择时间2017-03-27 15:00:00,通过datatable的getData以及getSimpleData获取数据为1490608800000,重新选择回2017-03-27 11:00:00,通过datatable的getData以及getSimpleData获取数据依旧为1490594400000,
  • 手工输入修改数据为其他值然后修改为2017-03-27 11:00:00,点开面板显示时间依旧为2017-03-27 11:00:00,通过datatable的getData以及getSimpleData获取数据依旧为1490594400000(暂时不支持手工输入,不进行测试)
  • 无数据时点开面板显示时间为系统时间减去3个小时,选择之后通过datatable的getData以及getSimpleData获取的数据与直接new Date()对应的long值保持一致

只有日期

  • 数据库存储值为1490641200000,显示时显示为2017-03-28,点开面板显示时间依旧为2017-03-28,选择时间2017-03-15,通过datatable的getData以及getSimpleData获取数据依旧为1489518000000,重新选择回2017-03-28,通过datatable的getData以及getSimpleData获取数据依旧为1490641200000
  • 手工输入修改数据为其他值然后修改为2017-03-28,点开面板显示时间依旧为2017-03-28,通过datatable的getData以及getSimpleData获取数据依旧为1490641200000(暂时不支持手工输入,不进行测试)
  • 无数据时点开面板为系统时间所对应的日期,选择之后通过datatable的getData以及getSimpleData获取的数据为直接new Date(日期)的long值加上3 * 3600000

起止时间

手工设置起止时间

传入起止时间时要传入long值

日期时间
  • 起始时间设置为1490594400000,终止时间设置为1490608800000
  • 选中区间为2017-03-27 11:00:00 至2017-03-27 15:00:00
只有日期
  • 起始时间设置为1489518000000,终止时间设置为1490641200000
  • 选中区间为2017-03-15至2017-03-28

通过设置起止字段来控制起止时间

设置3个字段,a字段在b和c之间,先选择b和c字段,之后查看a字段的选择范围是否正确,并且存储时数据是否正确。

  • a选择日期时间2017-03-27 11:00:00对应long值为1490594400000
  • a选择日期2017-03-28对应long值为1490641200000