|
|
@@ -0,0 +1,98 @@
|
|
|
+/**
|
|
|
+ * Fixes random / broken date selection in react-native-ui-datepicker (range mode).
|
|
|
+ * https://github.com/farhoudshapouran/react-native-ui-datepicker/issues/260
|
|
|
+ */
|
|
|
+import dayjs from 'dayjs';
|
|
|
+import utc from 'dayjs/plugin/utc';
|
|
|
+import timezone from 'dayjs/plugin/timezone';
|
|
|
+
|
|
|
+dayjs.extend(utc);
|
|
|
+dayjs.extend(timezone);
|
|
|
+
|
|
|
+let proto: any;
|
|
|
+dayjs.extend((_option, DayjsClass) => {
|
|
|
+ proto = DayjsClass.prototype;
|
|
|
+});
|
|
|
+
|
|
|
+let defaultTimezone: string | undefined;
|
|
|
+const originalSetDefault = dayjs.tz.setDefault;
|
|
|
+dayjs.tz.setDefault = (tz?: string) => {
|
|
|
+ defaultTimezone = tz;
|
|
|
+ originalSetDefault(tz);
|
|
|
+};
|
|
|
+
|
|
|
+type Parts = {
|
|
|
+ year: number;
|
|
|
+ month: number;
|
|
|
+ day: number;
|
|
|
+ hour: number;
|
|
|
+ minute: number;
|
|
|
+ second: number;
|
|
|
+};
|
|
|
+
|
|
|
+const dtfCache: Record<string, Intl.DateTimeFormat> = {};
|
|
|
+const getDateTimeFormat = (tz?: string) => {
|
|
|
+ const key = String(tz);
|
|
|
+ if (!dtfCache[key]) {
|
|
|
+ dtfCache[key] = new Intl.DateTimeFormat('en-US', {
|
|
|
+ hour12: false,
|
|
|
+ timeZone: tz,
|
|
|
+ year: 'numeric',
|
|
|
+ month: '2-digit',
|
|
|
+ day: '2-digit',
|
|
|
+ hour: '2-digit',
|
|
|
+ minute: '2-digit',
|
|
|
+ second: '2-digit'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return dtfCache[key];
|
|
|
+};
|
|
|
+
|
|
|
+const getParts = (timestamp: number, tz?: string): Parts => {
|
|
|
+ const result: Record<string, number> = {};
|
|
|
+ for (const { type, value } of getDateTimeFormat(tz).formatToParts(new Date(timestamp))) {
|
|
|
+ if (type !== 'literal') result[type] = parseInt(value, 10);
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ year: result.year,
|
|
|
+ month: result.month,
|
|
|
+ day: result.day,
|
|
|
+ hour: result.hour === 24 ? 0 : result.hour,
|
|
|
+ minute: result.minute,
|
|
|
+ second: result.second
|
|
|
+ };
|
|
|
+};
|
|
|
+
|
|
|
+proto.tz = function (tz: string | undefined = defaultTimezone, keepLocalTime = false) {
|
|
|
+ if (!this.isValid()) return this;
|
|
|
+
|
|
|
+ const oldOffset = this.utcOffset();
|
|
|
+ const timestamp = this.valueOf();
|
|
|
+ const p = getParts(timestamp, tz);
|
|
|
+ const wallClockAsUtc = Date.UTC(p.year, p.month - 1, p.day, p.hour, p.minute, p.second);
|
|
|
+ const offset = Math.round((wallClockAsUtc - Math.floor(timestamp / 1000) * 1000) / 60000);
|
|
|
+
|
|
|
+ let ins;
|
|
|
+ if (!offset) {
|
|
|
+ ins = this.utcOffset(0, keepLocalTime);
|
|
|
+ } else {
|
|
|
+ const wallClock = new Date(
|
|
|
+ p.year,
|
|
|
+ p.month - 1,
|
|
|
+ p.day,
|
|
|
+ p.hour,
|
|
|
+ p.minute,
|
|
|
+ p.second,
|
|
|
+ this.millisecond()
|
|
|
+ );
|
|
|
+ ins = (dayjs as any)(wallClock, { locale: this.$L }).utcOffset(offset, true);
|
|
|
+ if (keepLocalTime) {
|
|
|
+ ins = ins.add(oldOffset - ins.utcOffset(), 'minute');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ins.$x.$timezone = tz;
|
|
|
+ return ins;
|
|
|
+};
|
|
|
+
|
|
|
+export {};
|