Bug 1503731 - Avoid timezone conversion for date pattern detection of the dettimepicker. r+a=philipp CLOSED TREE DONTBUILD
authorMakeMyDay <makemyday@gmx-topmail.de>
Sun, 27 Jan 2019 23:04:46 +0100
changeset 34360 68eeb51034c66fa5ae08c2ed0975e77bb8a5e2c6
parent 34359 f0d8075173240f2ebf16e56679a03e6d31a95901
child 34361 3b13c231930cbd573f4fd859b83fe2fe18f3e44a
push id389
push userclokep@gmail.com
push dateMon, 18 Mar 2019 19:01:53 +0000
bugs1503731
Bug 1503731 - Avoid timezone conversion for date pattern detection of the dettimepicker. r+a=philipp CLOSED TREE DONTBUILD
calendar/resources/content/datetimepickers/datetimepickers.xml
--- a/calendar/resources/content/datetimepickers/datetimepickers.xml
+++ b/calendar/resources/content/datetimepickers/datetimepickers.xml
@@ -1661,27 +1661,31 @@
             this.alphaMonths = null;
             this.probeSucceeded = false;
             this.mLastDateParseIncludedTime = false;
 
             // SHORT NUMERIC DATE, such as 2002-03-04, 4/3/2002, or CE2002Y03M04D.
             // Made of digits & nonDigits.  (Nondigits may be unicode letters
             // which do not match \w, esp. in CJK locales.)
             this.parseShortDateRegex = /^\D*(\d+)\D+(\d+)\D+(\d+)\D?$/;
-            let probeDate = new Date(2002, 2, 4); // month is 0-based
-            let probeString = this.formatDate(probeDate);
+            // Make sure to use UTC date and timezone here to avoid the pattern
+            // detection to fail if the probe date output would have an timezone
+            // offset due to our lack of support of historic timezone definitions.
+            let probeDate = new Date(Date.UTC(2002, 3, 6)); // month is 0-based
+            let probeString = this.formatDate(probeDate, cal.dtz.UTC);
             let probeArray = this.parseShortDateRegex.exec(probeString);
             if (probeArray) {
                 // Numeric month format
                 for (let i = 1; i <= 3; i++) {
                     switch (Number(probeArray[i])) {
                         case 2: this.twoDigitYear = true; // falls through
                         case 2002: this.yearIndex = i; break;
-                        case 3: this.monthIndex = i; break;
-                        case 4: this.dayIndex = i; break;
+                        case 4: this.monthIndex = i; break;
+                        case 5: // falls through for OS timezones western to GMT
+                        case 6: this.dayIndex = i; break;
                     }
                 }
                 // All three indexes are set (not -1) at this point.
                 this.probeSucceeded = true;
             } else {
                 // SHORT DATE WITH ALPHABETIC MONTH, such as "dd MMM yy" or "MMMM dd, yyyy"
                 // (\d+|[^\d\W]) is digits or letters, not both together.
                 // Allows 31dec1999 (no delimiters between parts) if OS does (w2k does not).
@@ -1692,17 +1696,18 @@
                 // http://www.unicode.org/Public/UNIDATA/DerivedCoreProperties.txt)
                 this.parseShortDateRegex = /^\s*(\d+|[^\d\W]+)\W{0,2}(\d+|[^\d\W]+)\W{0,2}(\d+|[^\d\W]+)\s*$/;
                 probeArray = this.parseShortDateRegex.exec(probeString);
                 if (probeArray != null) {
                     for (let j = 1; j <= 3; j++) {
                         switch (Number(probeArray[j])) {
                             case 2: this.twoDigitYear = true; // falls through
                             case 2002: this.yearIndex = j; break;
-                            case 4: this.dayIndex = j; break;
+                            case 5: // falls through for OS timezones western to GMT
+                            case 6: this.dayIndex = j; break;
                             default: this.monthIndex = j; break;
                         }
                     }
                     if (this.yearIndex != -1 && this.dayIndex != -1 && this.monthIndex != -1) {
                         this.probeSucceeded = true;
                         // Fill this.alphaMonths with month names.
                         this.alphaMonths = new Array(12);
                         for (let monthIdx = 0; monthIdx < 12; monthIdx++) {
@@ -1831,18 +1836,24 @@
                 new RegExp("(" + ampmExpr + ")?\\s?" + digitsExpr + "(" + ampmExpr + ")?\\s*$");
             this.amRegExp = new RegExp("^(?:" + amExpr + ")$");
             this.pmRegExp = new RegExp("^(?:" + pmExpr + ")$");
         ]]></body>
       </method>
 
       <method name="formatDate">
         <parameter name="aDate"/>
+        <parameter name="aTimezone"/>
         <body><![CDATA[
-            return cal.getDateFormatter().formatDateShort(cal.dtz.jsDateToDateTime(aDate, cal.dtz.floating));
+            // Usually, floating is ok here, so no need to pass aTimezone - we just need to pass
+            // it in if we need to make sure formatting happens without a timezone conversion.
+            let timezone = aTimezone || cal.dtz.floating;
+            return cal.getDateFormatter().formatDateShort(
+                cal.dtz.jsDateToDateTime(aDate, timezone)
+            );
         ]]></body>
       </method>
 
       <method name="formatTime">
         <parameter name="aValue"/>
         <body><![CDATA[
             let formatter = new Services.intl.DateTimeFormat(undefined, this.kTimeFormatObject);
             return formatter.format(aValue);