【问题标题】:Dealing with (birthday) dates and Timezone with Dojo使用 Dojo 处理(生日)日期和时区
【发布时间】:2014-10-16 16:17:14
【问题描述】:

我有一个简单的小部件:

<input class="input" id="${id}_dateOfBirth" name="dateOfBirth" data-dojo-type="dijit/form/DateTextBox" />

请注意,今天是生日。因此,无论您身在何处(不应该出现时区),它都应该保持相同。如果您出生于 1 月 10 日凌晨 3:00 在英格兰,并在纽约查看您的个人信息,那么您仍然会看到 1 月 10 日,而不是 9 日!

我现在在 GMT+8。 当我提交此表单时,它实际上会在我输入 1/1/1970 时到达服务器:

dateOfBirth: "1969-12-31T16:00:00.000Z"     

这很糟糕,因为它比实际日期少了 8 个小时。

基本上,我需要一种方法让 DateTextBox 显示它来自服务器的日期 ,从而有效地忽略浏览器的时区。

【问题讨论】:

    标签: date timezone dojo


    【解决方案1】:

    FWIW,这是我的 UTCDateTextBox 变体:

    define([
        "dojo/_base/declare",
        "dijit/form/DateTextBox"
    ], function(declare, DateTextBox) {
        function isValidDate(value) {
            return value instanceof Date && isFinite(value.getTime());
        }
        function toUTCDate(value) {
            if (isValidDate(value)) {
                value = new Date(
                    Date.UTC(value.getFullYear(), value.getMonth(), value.getDate())
                );
            }
            return value;
        }
        return declare(DateTextBox, {
            _getValueAttr : function() {
                return toUTCDate(this.inherited("_getValueAttr", arguments));
            }
        });
    });
    

    对于我的用例,我发现我不需要覆盖_setValueAttr()。通过上述实现,当_getValueAttr()返回的日期对象上调用getUTCXXX()toUTCString()toISOString()toJSON()时,将返回正确的UTC日期,时间元素为零。

    希望这会有所帮助。

    【讨论】:

    • 这是一个更好的主意。当我回家并测试此解决方案时,将对其进行测试并接受此作为答案。谢谢!
    • 我在我们的应用程序中使用了这个小部件。
    【解决方案2】:

    在对 Dojo 的源代码进行了大量的修改和分析之后,我想出了这个:

    var UTCDateTextBox = declare( 'UTCDateTextBox', [ DateTextBox ], { 
    
    
      _getValueAttr: function(){ 
        var ov = this.inherited(arguments); 
        if( ov ){ 
          ov.setTime( ov.getTime() - ov.getTimezoneOffset() * 60 * 1000 ); 
        } 
        return ov; 
    
      }, 
    
      _setValueAttr: function( value, priorityChange, formattedValue){ 
    
        var v = stamp.fromISOString( value ); 
        if( v ){ 
          v.setTime( v.getTime() + v.getTimezoneOffset() * 60 * 1000 );                         
          value = v; 
        } 
    
        this.inherited(arguments); 
      }
    
    }); 
    

    基本上:

    • 设置该值后,将添加时区差异。这意味着如果服务器有 1979-12-25T00:00:00.000Z,而不是分配 Tue Dec 25 1979 08:00:00 GMT+0800 (WST),它将分配 Tue Dec 25 1979 00:00:00 GMT +0800 (WST) 。基本上,日期会本地转换为 UTC 格式。

    • 解析值时,将从 1979 年 12 月 25 日星期二 00:00:00 GMT+0800 (WST) 更改为 1979 年 12 月 25 日星期二 08:00:00 GMT+0800 (WST)

    • 更改的值是提交给服务器的值。因此,无论将在哪个时区进行编辑,它都是正确的。

    由于我只处理日期,如果服务器有 1979-12-31T23:00:00Z (这是一个错误:对于生日,时间实际上被忽略并且无关紧要),这将发生:

    • 设置该值时,ISO 为 1979-12-31T23:00:00.000Z。因此,1980 年 1 月 1 日星期二 07:00:00 GMT+0800 (WST) 更改为 1979 年 12 月 31 日星期一 23:00:00 GMT+0800 (WST)。这意味着将正确的日期放入日期文本框 (31/12/1979)。

    • 当从文本框中解析值时,Mon Dec 31 00:00:00 GMT+0800 (WST) 变为 Mon Dec 31 08:00:00 GMT+0800 (WST)。因此,服务器将保存 1979-12-31T00:00:00Z——这又是正确的日期!

    如果有更好的解决方案,请告诉我。坦率地说,我希望这个感觉有点像作弊的bit

    【讨论】:

    • 天哪,要么我的答案(仍然有效)是“那个”答案,要么没有人使用 Dojo 的日期选择器记录出生日期!
    • 我认为没有一种规范的方法可以做到这一点,而无需扩展日历(就像您所做的那样)或在序列化之前操作日期。在我自己的项目中,我以类似的方式处理它。
    • 仍然没有投票,这意味着没有多少人真正关心这一点。哦,好吧...
    • Merc 干得好。我需要一个用于度假租赁网站上“季节性”日期范围的 UTC 文本框。我已经使用 hack 这么长时间了。
    猜你喜欢
    • 1970-01-01
    • 2019-01-08
    • 2013-03-05
    • 2013-06-30
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多