WCF.Date.Time now properly handles time offsets
authorAlexander Ebert <ebert@woltlab.com>
Thu, 28 Mar 2013 11:48:39 +0000 (12:48 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Thu, 28 Mar 2013 11:48:39 +0000 (12:48 +0100)
The calculation of relative times previously failed if both the client and the server use the timezone, but their actual time is slightly different. In that case both times could be different by a few seconds, causing times to be in the future, even though it was just a mismatch.

Fixes #1179

com.woltlab.wcf/template/headInclude.tpl
wcfsetup/install/files/acp/templates/header.tpl
wcfsetup/install/files/js/WCF.js

index 3909eff0895fb08c54e7681729a61543e47ff264..49ea5402dc2b25534ef32391b5debf592f90c900 100644 (file)
@@ -10,6 +10,7 @@
        var RELATIVE_WCF_DIR = '{@$__wcf->getPath()}';
        var SECURITY_TOKEN = '{@SECURITY_TOKEN}';
        var LANGUAGE_ID = {@$__wcf->getLanguage()->languageID};
+       var TIME_NOW = {@TIME_NOW};
        //]]>
 </script>
 <script type="text/javascript" src="{@$__wcf->getPath()}js/3rdParty/jquery.min.js"></script>
index 34a17bb6e67edade95187ca61c818cfd9c183f4b..4be68d55016e10c29bc937a7b01f4a4f5e42958a 100644 (file)
@@ -11,6 +11,7 @@
                var RELATIVE_WCF_DIR = '{@$__wcf->getPath()}';
                var SECURITY_TOKEN = '{@SECURITY_TOKEN}';
                var LANGUAGE_ID = {@$__wcf->getLanguage()->languageID};
+               var TIME_NOW = {@TIME_NOW};
                //]]>
        </script>
        <script type="text/javascript" src="{@$__wcf->getPath()}js/3rdParty/jquery.min.js"></script>
index df0366120fb94c24299b311a7a752f8d27176f52..106624b4322809d70efe40ffdcc83955152f06a8 100755 (executable)
@@ -2276,13 +2276,31 @@ WCF.Date.Util = {
  * Handles relative time designations.
  */
 WCF.Date.Time = Class.extend({
+       /**
+        * list of time elements
+        * @var jQuery
+        */
+       _elements: null,
+       
+       /**
+        * difference between server and local time
+        * @var integer
+        */
+       _offset: null,
+       
+       /**
+        * current timestamp
+        * @var integer
+        */
+       _timestamp: 0,
+       
        /**
         * Initializes relative datetimes.
         */
        init: function() {
-               // initialize variables
-               this.elements = $('time.datetime');
-               this.timestamp = 0;
+               this._elements = $('time.datetime');
+               this._offset = null;
+               this._timestamp = 0;
                
                // calculate relative datetime on init
                this._refresh();
@@ -2298,7 +2316,7 @@ WCF.Date.Time = Class.extend({
         * Updates element collection once a DOM node was inserted.
         */
        _domNodeInserted: function() {
-               this.elements = $('time.datetime');
+               this._elements = $('time.datetime');
                this._refresh();
        },
        
@@ -2306,12 +2324,13 @@ WCF.Date.Time = Class.extend({
         * Refreshes relative datetime for each element.
         */
        _refresh: function() {
-               // TESTING ONLY!
                var $date = new Date();
-               this.timestamp = ($date.getTime() - $date.getMilliseconds()) / 1000;
-               // TESTING ONLY!
+               this._timestamp = ($date.getTime() - $date.getMilliseconds()) / 1000;
+               if (this._offset === null) {
+                       this._offset = this._timestamp - TIME_NOW;
+               }
                
-               this.elements.each($.proxy(this._refreshElement, this));
+               this._elements.each($.proxy(this._refreshElement, this));
        },
        
        /**
@@ -2321,45 +2340,47 @@ WCF.Date.Time = Class.extend({
         * @param       object          element
         */
        _refreshElement: function(index, element) {
-               if (!$(element).attr('title')) {
-                       $(element).attr('title', $(element).text());
+               var $element = $(element);
+               
+               if (!$element.attr('title')) {
+                       $element.attr('title', $element.text());
                }
                
-               var $timestamp = $(element).data('timestamp');
-               var $date = $(element).data('date');
-               var $time = $(element).data('time');
-               var $offset = $(element).data('offset');
+               var $timestamp = $element.data('timestamp') + this._offset;
+               var $date = $element.data('date');
+               var $time = $element.data('time');
+               var $offset = $element.data('offset');
                
                // timestamp is in the future
-               if ($timestamp > this.timestamp) {
+               if ($timestamp > this._timestamp) {
                        var $string = WCF.Language.get('wcf.date.dateTimeFormat');
-                       $(element).text($string.replace(/\%date\%/, $date).replace(/\%time\%/, $time));
+                       $element.text($string.replace(/\%date\%/, $date).replace(/\%time\%/, $time));
                }
                // timestamp is less than 60 minutes ago (display 1 hour ago rather than 60 minutes ago)
-               else if (this.timestamp < ($timestamp + 3540)) {
-                       var $minutes = Math.round((this.timestamp - $timestamp) / 60);
-                       $(element).text(eval(WCF.Language.get('wcf.date.relative.minutes')));
+               else if (this._timestamp < ($timestamp + 3540)) {
+                       var $minutes = Math.round((this._timestamp - $timestamp) / 60);
+                       $element.text(eval(WCF.Language.get('wcf.date.relative.minutes')));
                }
                // timestamp is less than 24 hours ago
-               else if (this.timestamp < ($timestamp + 86400)) {
-                       var $hours = Math.round((this.timestamp - $timestamp) / 3600);
-                       $(element).text(eval(WCF.Language.get('wcf.date.relative.hours')));
+               else if (this._timestamp < ($timestamp + 86400)) {
+                       var $hours = Math.round((this._timestamp - $timestamp) / 3600);
+                       $element.text(eval(WCF.Language.get('wcf.date.relative.hours')));
                }
                // timestamp is less than a week ago
-               else if (this.timestamp < ($timestamp + 604800)) {
-                       var $days = Math.round((this.timestamp - $timestamp) / 86400);
+               else if (this._timestamp < ($timestamp + 604800)) {
+                       var $days = Math.round((this._timestamp - $timestamp) / 86400);
                        var $string = eval(WCF.Language.get('wcf.date.relative.pastDays'));
                        
                        // get day of week
                        var $dateObj = WCF.Date.Util.getTimezoneDate(($timestamp * 1000), $offset);
                        var $dow = $dateObj.getDay();
                        
-                       $(element).text($string.replace(/\%day\%/, WCF.Language.get('__days')[$dow]).replace(/\%time\%/, $time));
+                       $element.text($string.replace(/\%day\%/, WCF.Language.get('__days')[$dow]).replace(/\%time\%/, $time));
                }
                // timestamp is between ~700 million years BC and last week
                else {
                        var $string = WCF.Language.get('wcf.date.dateTimeFormat');
-                       $(element).text($string.replace(/\%date\%/, $date).replace(/\%time\%/, $time));
+                       $element.text($string.replace(/\%date\%/, $date).replace(/\%time\%/, $time));
                }
        }
 });