Last active
June 2, 2016 07:51
-
-
Save pithu/23128485d022af27a5b36b3fbbf6d92e to your computer and use it in GitHub Desktop.
Implement a threeten ZoneRegion by a MomentZoneRules wrapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {LocalDate, DayOfWeek, TemporalAdjusters, Instant, ZoneId, ZoneOffset, ZonedDateTime, LocalTime} from 'js-joda' | |
import {tz} from 'moment-timezone' | |
class MomentZoneRules { | |
constructor(tz) { | |
this.untils = tz.untils; | |
// localUntils is an array taken from original utc untils, modified by the reverse of the maximum (of actual, previous) offset | |
// thus, if you take the epochMillis of a LocalDateTime interpreted at UTC and binsearch it here, | |
// you should find the index of the transition, that is either unique or is before the transition in case of gap/overlap | |
this.localUntils = tz.untils.map((v, i) => v - Math.min(tz.offsets[i], tz.offsets[Math.max(0, i - 1)]) * 60000); | |
this.offsets = tz.offsets.map((v) => ZoneOffset.ofTotalMinutes(-v)); | |
} | |
isFixedOffset() { | |
return false; | |
} | |
offset(instantOrLocalDateTime) { | |
if (instantOrLocalDateTime instanceof Instant) { | |
return this.offsetOfInstant(instantOrLocalDateTime); | |
} else { | |
return this.offsetOfLocalDateTime(instantOrLocalDateTime); | |
} | |
} | |
offsetOfInstant(instant) { | |
return this._offset(this.untils, instant.toEpochMilli()); | |
} | |
offsetOfLocalDateTime(localDateTime){ | |
let localMillis = Instant.from(ZonedDateTime.of(localDateTime, ZoneId.UTC)).toEpochMilli(); | |
return this._offset(this.localUntils, localMillis); | |
} | |
_offset(array, timestamp) { | |
let nextIndex = search(array, timestamp); | |
if (nextIndex < 0) nextIndex = this.offsets.length - 1; | |
return this.offsets[nextIndex] | |
} | |
} | |
class ZoneRegion extends ZoneId { | |
constructor(id, rules) { | |
super(); | |
this._id = id; | |
this._rules = rules; | |
} | |
rules() { | |
return this._rules; | |
} | |
} | |
class MomentZoneId extends ZoneRegion { | |
constructor(id) { | |
super(id, new MomentZoneRules(tz.zone(id))); | |
} | |
} | |
const TZ = new MomentZoneId('Europe/Berlin'); | |
// modified bin-search, to always find existing indices for non-empty arrays | |
// value in array at index is larger than input value (or last index of array) | |
function search(array, value) { | |
let hi = array.length - 1, lo = -1, mid; | |
while (hi - lo > 1) { | |
if (array[mid = hi + lo >> 1] <= value) { | |
lo = mid; | |
} else { | |
hi = mid; | |
} | |
} | |
return hi; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment