Explorar o código

datelib dst dead zone test

Adam Shaw %!s(int64=7) %!d(string=hai) anos
pai
achega
9f352e97a0
Modificáronse 2 ficheiros con 97 adicións e 1 borrados
  1. 60 0
      tests/automated/datelib/dst-dead-zone.js
  2. 37 1
      tests/automated/datelib/main.js

+ 60 - 0
tests/automated/datelib/dst-dead-zone.js

@@ -0,0 +1,60 @@
+
+/*
+Some hours don't exist in local time when a daylight-savings shift happpens.
+This time is called a "dead zone".
+If possible, this function returns an array of two dates,
+the date just before the dead zone (with a 999 millisecond time)
+and the date just after the dead zone.
+
+I apologize for the unreadability of this code. It was written a long time ago:
+https://github.com/arshaw/xdate/blob/master/test/old.js
+*/
+export function getDSTDeadZone() {
+  var dstDates = getDSTDates();
+  if (dstDates) {
+    var prior = new Date(+dstDates[0]-1);
+    if (Math.abs(dstDates[0].getHours() - prior.getHours()) > 1) {
+      return [prior, dstDates[0]];
+    }
+    prior = new Date(+dstDates[1]-1);
+    if (Math.abs(dstDates[1].getHours() - prior.getHours()) > 1) {
+      return [prior, dstDates[1]];
+    }
+  }
+}
+
+function getDSTDates() {
+  var MS_DAY = 86400000;
+  var res = [];
+  var d0 = new Date();
+  var overAYear = new Date(+d0);
+  overAYear.setFullYear(overAYear.getFullYear() + 1);
+  overAYear = new Date(+overAYear + MS_DAY);
+  while (d0 < overAYear) {
+    var d1 = new Date(+d0 + MS_DAY);
+    if (d0.getTimezoneOffset() != d1.getTimezoneOffset()) {
+      res.push(new Date(narrowDSTDate(+d0, +d1)));
+      if (res.length == 2) {
+        break;
+      }
+    }
+    d0 = d1;
+  }
+  return res.length == 2 ? res : null;
+}
+
+function narrowDSTDate(start, end) {
+  if (end <= start+1) {
+    return end;
+  }
+  var mid = start + Math.floor((end - start) / 2);
+  var midTZO = new Date(mid).getTimezoneOffset();
+  var startTZO = new Date(start).getTimezoneOffset();
+  var endTZO = new Date(end).getTimezoneOffset();
+  if (midTZO == startTZO) {
+    return narrowDSTDate(mid, end);
+  }
+  else if (midTZO == endTZO) {
+    return narrowDSTDate(start, mid);
+  }
+}

+ 37 - 1
tests/automated/datelib/main.js

@@ -1,4 +1,5 @@
-import { formatPrettyTimeZoneOffset, formatIsoTimeZoneOffset } from './utils'
+import { formatPrettyTimeZoneOffset, formatIsoTimeZoneOffset, formatIsoWithoutTz } from './utils'
+import { getDSTDeadZone } from './dst-dead-zone'
 
 describe('datelib', function() {
   var DateEnv = FullCalendar.DateEnv
@@ -520,6 +521,41 @@ describe('datelib', function() {
         expect(res.forcedTzo).toBeNull()
       })
 
+      it('does not lose info when parsing a dst-dead-zone date', function() {
+        let deadZone = getDSTDeadZone()
+
+        if (!deadZone) {
+          console.log('could not determine DST dead zone')
+        } else {
+
+          // use a utc date to get a ISO8601 string representation of the start of the dead zone
+          let utcDate = new Date(Date.UTC(
+            deadZone[1].getFullYear(),
+            deadZone[1].getMonth(),
+            deadZone[1].getDate(),
+            deadZone[1].getHours() - 1, // back one hour. shouldn't exist in local time
+            deadZone[1].getMinutes(),
+            deadZone[1].getSeconds(),
+            deadZone[1].getMilliseconds()
+          ))
+          let s = formatIsoWithoutTz(utcDate)
+
+          // check that the local date falls out of the dead zone
+          let localDate = new Date(s)
+          expect(localDate.getHours()).not.toBe(deadZone[1].getHours() - 1)
+
+          // check that is parsed and retained the original hour,
+          // even tho it falls into the dead zone for local time
+          let marker = env.createMarker(s)
+          expect(formatIsoWithoutTz(marker)).toBe(s)
+
+          //// TODO
+          // // when it uses the env to format to local time,
+          // // it should have jumped out of the dead zone.
+          // expect(env.formatIso(marker)).not.toMatch(s)
+        }
+      })
+
     })
 
     it('outputs ISO8601 formatting', function() {