@devexperts/dxcharts-lite 2.2.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chart/bootstrap.js +4 -3
- package/dist/chart/canvas/canvas-bounds-container.d.ts +2 -2
- package/dist/chart/canvas/canvas-bounds-container.js +7 -5
- package/dist/chart/canvas/cursor.handler.js +2 -2
- package/dist/chart/chart.config.d.ts +17 -4
- package/dist/chart/chart.config.js +6 -2
- package/dist/chart/components/chart/chart-area-pan.handler.js +13 -8
- package/dist/chart/components/chart/chart.component.d.ts +6 -3
- package/dist/chart/components/chart/chart.component.js +18 -7
- package/dist/chart/components/chart/chart.model.d.ts +1 -2
- package/dist/chart/components/chart/chart.model.js +2 -3
- package/dist/chart/components/cross_tool/cross-tool.model.js +1 -1
- package/dist/chart/components/cross_tool/types/cross-and-labels.drawer.js +4 -2
- package/dist/chart/components/high_low/high-low.drawer.js +9 -2
- package/dist/chart/components/highlights/highlights.drawer.js +1 -1
- package/dist/chart/components/pane/pane.component.js +6 -3
- package/dist/chart/components/snapshot/snapshot.component.js +1 -0
- package/dist/chart/components/volumes/separate-volumes.component.js +2 -1
- package/dist/chart/components/volumes/volumes.drawer.js +1 -1
- package/dist/chart/components/volumes/volumes.formatter.d.ts +1 -1
- package/dist/chart/components/volumes/volumes.formatter.js +28 -25
- package/dist/chart/components/x_axis/time/parser/time-formats-matchers.functions.js +1 -1
- package/dist/chart/components/x_axis/time/parser/time-formats.model.d.ts +1 -1
- package/dist/chart/components/x_axis/time/x-axis-weights.functions.js +2 -2
- package/dist/chart/components/x_axis/time/x-axis-weights.generator.js +6 -7
- package/dist/chart/components/x_axis/x-axis-labels.generator.d.ts +11 -3
- package/dist/chart/components/x_axis/x-axis-labels.generator.js +47 -19
- package/dist/chart/components/x_axis/x-axis-time-labels.drawer.js +0 -4
- package/dist/chart/components/x_axis/x-axis.component.js +7 -11
- package/dist/chart/components/y_axis/price_labels/last-candle-labels.provider.js +5 -5
- package/dist/chart/components/y_axis/price_labels/price-label.drawer.js +21 -22
- package/dist/chart/components/y_axis/y-axis-labels.drawer.d.ts +18 -6
- package/dist/chart/components/y_axis/y-axis-labels.drawer.js +23 -12
- package/dist/chart/components/y_axis/y-axis-scale.handler.d.ts +9 -4
- package/dist/chart/components/y_axis/y-axis-scale.handler.js +22 -15
- package/dist/chart/components/y_axis/y-axis.component.js +1 -0
- package/dist/chart/components/y_axis/y-axis.drawer.js +1 -1
- package/dist/chart/drawers/chart-background.drawer.d.ts +2 -3
- package/dist/chart/drawers/chart-background.drawer.js +16 -22
- package/dist/chart/drawers/data-series-drawers/candle-series-wrapper.js +1 -1
- package/dist/chart/drawers/data-series.drawer.d.ts +0 -2
- package/dist/chart/drawers/data-series.drawer.js +2 -7
- package/dist/chart/drawers/ht-data-series.drawer.js +1 -1
- package/dist/chart/inputhandlers/hover-producer.component.d.ts +1 -1
- package/dist/chart/inputlisteners/canvas-input-listener.component.d.ts +9 -0
- package/dist/chart/inputlisteners/canvas-input-listener.component.js +38 -1
- package/dist/chart/model/compare-series-hover.d.ts +1 -1
- package/dist/chart/model/compare-series-hover.js +5 -0
- package/dist/chart/model/data-series.model.js +1 -1
- package/dist/chart/model/hit-test-canvas.model.js +2 -2
- package/dist/chart/model/scale.model.d.ts +6 -3
- package/dist/chart/model/scale.model.js +46 -9
- package/dist/chart/model/scaling/constrait.functions.d.ts +1 -1
- package/dist/chart/model/scaling/constrait.functions.js +1 -2
- package/dist/chart/model/scaling/lock-ratio.model.d.ts +8 -2
- package/dist/chart/model/scaling/lock-ratio.model.js +18 -3
- package/dist/chart/model/scaling/viewport.model.d.ts +2 -0
- package/dist/chart/model/scaling/viewport.model.js +13 -4
- package/dist/chart/model/time-zone.model.d.ts +0 -14
- package/dist/chart/model/time-zone.model.js +13 -33
- package/dist/chart/utils/canvas/canvas-drawing-functions.utils.d.ts +12 -1
- package/dist/chart/utils/canvas/canvas-drawing-functions.utils.js +16 -1
- package/dist/chart/utils/canvas/canvas-text-functions.utils.d.ts +3 -2
- package/dist/chart/utils/canvas/canvas-text-functions.utils.js +8 -3
- package/dist/chart/utils/device/touchpad.utils.d.ts +3 -3
- package/dist/chart/utils/device/touchpad.utils.js +3 -5
- package/dist/chart/utils/math.utils.d.ts +1 -1
- package/dist/chart/utils/math.utils.js +4 -1
- package/dist/chart/utils/timezone.utils.d.ts +13 -0
- package/dist/chart/utils/timezone.utils.js +48 -0
- package/dist/dxchart.min.js +6 -6
- package/package.json +1 -2
|
@@ -3,28 +3,20 @@
|
|
|
3
3
|
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
4
|
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
|
-
import { getTimezoneOffset as getTimezoneOffsetDateFnsTz } from 'date-fns-tz';
|
|
7
6
|
import { ReplaySubject } from 'rxjs';
|
|
8
|
-
import { memoize } from '../utils/performance/memoize.utils';
|
|
9
7
|
import { dateTimeFormatterFactory } from './date-time.formatter';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const localOffset = new Date(time).getTimezoneOffset() * 60 * 1000;
|
|
14
|
-
return localOffset + memoizedTZOffset(timezone, time);
|
|
15
|
-
};
|
|
8
|
+
import { getTimezoneOffset } from '../utils/timezone.utils';
|
|
9
|
+
// 1 hour in milliseconds
|
|
10
|
+
const timeMultiplier = 60 * 1000;
|
|
16
11
|
export class TimeZoneModel {
|
|
17
12
|
constructor(config) {
|
|
18
13
|
this.config = config;
|
|
19
14
|
this.timeZoneChangedSubject = new ReplaySubject();
|
|
20
|
-
this.currentTzOffset = (time) =>
|
|
15
|
+
this.currentTzOffset = (time) => {
|
|
16
|
+
// we must pass time here, because we can have daylight saving time, otherwise we will get wrong offset
|
|
17
|
+
return getTimezoneOffset(this.config.timezone, time) + new Date(time).getTimezoneOffset() * timeMultiplier;
|
|
18
|
+
};
|
|
21
19
|
this.formatterCache = {};
|
|
22
|
-
/**
|
|
23
|
-
* Calculates the offset of a given timezone from the local timezone.
|
|
24
|
-
* @private
|
|
25
|
-
* @param {string} timezone - The timezone to calculate the offset for.
|
|
26
|
-
*/
|
|
27
|
-
this.getOffset = (timezone, time) => getTimezoneOffset(timezone, time);
|
|
28
20
|
this.dateTimeFormatterFactory = this.initFormatterFactory(this.config.dateFormatter);
|
|
29
21
|
}
|
|
30
22
|
/**
|
|
@@ -87,28 +79,16 @@ export class TimeZoneModel {
|
|
|
87
79
|
}
|
|
88
80
|
return this.formatterCache[format];
|
|
89
81
|
}
|
|
90
|
-
/**
|
|
91
|
-
* Gets the timezone offset value in milliseconds
|
|
92
|
-
* @param {string} timezone name
|
|
93
|
-
* @returns {function(time:Number):Date}
|
|
94
|
-
*/
|
|
95
82
|
tzOffset(timezone) {
|
|
96
|
-
// we must pass time here, because we can have daylight saving time, otherwise we will get wrong offset
|
|
97
|
-
const localOffset = (time) => -new Date(time).getTimezoneOffset() * timeMultiplier;
|
|
98
|
-
let offset;
|
|
99
83
|
if (!timezone) {
|
|
100
|
-
|
|
84
|
+
return time => new Date(time);
|
|
101
85
|
}
|
|
102
86
|
else {
|
|
103
|
-
//
|
|
104
|
-
|
|
87
|
+
// In JS Date object is created with local tz offset,
|
|
88
|
+
// so we have to subtract localOffset from current time
|
|
89
|
+
return time => {
|
|
90
|
+
return new Date(time + getTimezoneOffset(timezone, time) + new Date(time).getTimezoneOffset() * timeMultiplier);
|
|
91
|
+
};
|
|
105
92
|
}
|
|
106
|
-
// In JS Date object is created with local tz offset,
|
|
107
|
-
// so we have to subtract localOffset from current time
|
|
108
|
-
return time => {
|
|
109
|
-
return new Date(+time + offset(time) - localOffset(time));
|
|
110
|
-
};
|
|
111
93
|
}
|
|
112
94
|
}
|
|
113
|
-
// 1 hour in milliseconds
|
|
114
|
-
const timeMultiplier = 60 * 1000;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
6
|
import { YAxisAlign } from '../../chart.config';
|
|
7
|
+
import { Bounds } from '../../model/bounds.model';
|
|
7
8
|
/**
|
|
8
9
|
* Draws a rounded rectangle on a canvas context
|
|
9
10
|
* @param {CanvasRenderingContext2D} ctx - The canvas context to draw on
|
|
@@ -57,7 +58,7 @@ export declare function avoidAntialiasing(ctx: CanvasRenderingContext2D, draw: (
|
|
|
57
58
|
* @param {{x: number, y: number}} a - The first point of the rectangle.
|
|
58
59
|
* @param {{x: number, y: number}} b - The second point of the rectangle.
|
|
59
60
|
* @returns {void}
|
|
60
|
-
|
|
61
|
+
|
|
61
62
|
*/
|
|
62
63
|
export declare function fillRect(ctx: CanvasRenderingContext2D, a: {
|
|
63
64
|
x: number;
|
|
@@ -66,3 +67,13 @@ export declare function fillRect(ctx: CanvasRenderingContext2D, a: {
|
|
|
66
67
|
x: number;
|
|
67
68
|
y: number;
|
|
68
69
|
}): void;
|
|
70
|
+
/**
|
|
71
|
+
* Sets clipping region for a Canvas 2D context according to the provided bounds.
|
|
72
|
+
*
|
|
73
|
+
* @param {CanvasRenderingContext2D} ctx - The canvas 2D context which will get the new clip region.
|
|
74
|
+
* @param {object} bounds - The bounds of the clipping region. Object containing x, y, width and height properties.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* clipToBounds(ctx, {x: 50, y: 50, width: 100, height: 100});
|
|
78
|
+
*/
|
|
79
|
+
export declare const clipToBounds: (ctx: CanvasRenderingContext2D, bounds: Bounds) => void;
|
|
@@ -138,7 +138,7 @@ export function avoidAntialiasing(ctx, draw) {
|
|
|
138
138
|
* @param {{x: number, y: number}} a - The first point of the rectangle.
|
|
139
139
|
* @param {{x: number, y: number}} b - The second point of the rectangle.
|
|
140
140
|
* @returns {void}
|
|
141
|
-
|
|
141
|
+
|
|
142
142
|
*/
|
|
143
143
|
export function fillRect(ctx, a, b) {
|
|
144
144
|
const x = Math.min(a.x, b.x) + 0.5;
|
|
@@ -147,3 +147,18 @@ export function fillRect(ctx, a, b) {
|
|
|
147
147
|
const h = Math.abs(a.y - b.y);
|
|
148
148
|
ctx.fillRect(x, y, w, h);
|
|
149
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Sets clipping region for a Canvas 2D context according to the provided bounds.
|
|
152
|
+
*
|
|
153
|
+
* @param {CanvasRenderingContext2D} ctx - The canvas 2D context which will get the new clip region.
|
|
154
|
+
* @param {object} bounds - The bounds of the clipping region. Object containing x, y, width and height properties.
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* clipToBounds(ctx, {x: 50, y: 50, width: 100, height: 100});
|
|
158
|
+
*/
|
|
159
|
+
export const clipToBounds = (ctx, bounds) => {
|
|
160
|
+
ctx.beginPath();
|
|
161
|
+
ctx.rect(bounds.x, bounds.y, bounds.width, bounds.height);
|
|
162
|
+
ctx.clip();
|
|
163
|
+
ctx.closePath();
|
|
164
|
+
};
|
|
@@ -30,9 +30,10 @@ export declare function prepareTextForFill(ctx: CanvasRenderingContext2D, proper
|
|
|
30
30
|
/**
|
|
31
31
|
* Calculates the line height of a text based on the font size of the provided CanvasRenderingContext2D.
|
|
32
32
|
* @param {CanvasRenderingContext2D} ctx - The CanvasRenderingContext2D object used to draw the text.
|
|
33
|
+
* @param includeBaseLine
|
|
33
34
|
* @returns {number} The calculated line height of the text.
|
|
34
35
|
*/
|
|
35
|
-
export declare function getTextLineHeight(ctx: CanvasRenderingContext2D): number;
|
|
36
|
+
export declare function getTextLineHeight(ctx: CanvasRenderingContext2D, includeBaseLine?: boolean): number;
|
|
36
37
|
/**
|
|
37
38
|
* Calculates text bounds [textWidth, textHeight, lineHeight]
|
|
38
39
|
* @param ctx
|
|
@@ -53,7 +54,7 @@ export declare function getTextLines(text: string): string[];
|
|
|
53
54
|
* @param {number} y - The y-coordinate of the starting position of the text.
|
|
54
55
|
* @param {CanvasTextProperties} properties - An object containing properties for the text, such as font size, style, and alignment.
|
|
55
56
|
* @returns {void}
|
|
56
|
-
|
|
57
|
+
|
|
57
58
|
*/
|
|
58
59
|
export declare function drawText(ctx: CanvasRenderingContext2D, lines: string[], x: number, y: number, properties: CanvasTextProperties): void;
|
|
59
60
|
/**
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
6
|
import Color from 'color';
|
|
7
|
+
/**
|
|
8
|
+
* Baseline Height in Project
|
|
9
|
+
*/
|
|
10
|
+
const BASELINE = 1.33;
|
|
7
11
|
/**
|
|
8
12
|
* Sets the font, fill style and text alignment of a canvas context based on the provided properties.
|
|
9
13
|
* @param {CanvasRenderingContext2D} ctx - The canvas context to modify.
|
|
@@ -32,9 +36,10 @@ export function prepareTextForFill(ctx, properties) {
|
|
|
32
36
|
/**
|
|
33
37
|
* Calculates the line height of a text based on the font size of the provided CanvasRenderingContext2D.
|
|
34
38
|
* @param {CanvasRenderingContext2D} ctx - The CanvasRenderingContext2D object used to draw the text.
|
|
39
|
+
* @param includeBaseLine
|
|
35
40
|
* @returns {number} The calculated line height of the text.
|
|
36
41
|
*/
|
|
37
|
-
export function getTextLineHeight(ctx) {
|
|
42
|
+
export function getTextLineHeight(ctx, includeBaseLine = true) {
|
|
38
43
|
const textSizeMatch = ctx.font.match(/(\d+.)?\d+(px|pt)/gi);
|
|
39
44
|
let textSize = '10px';
|
|
40
45
|
if (textSizeMatch && textSizeMatch.length) {
|
|
@@ -46,7 +51,7 @@ export function getTextLineHeight(ctx) {
|
|
|
46
51
|
textSize = textSizeMatch[0];
|
|
47
52
|
}
|
|
48
53
|
}
|
|
49
|
-
return parseInt(textSize, 10) *
|
|
54
|
+
return includeBaseLine ? parseInt(textSize, 10) * BASELINE : parseInt(textSize, 10);
|
|
50
55
|
}
|
|
51
56
|
/**
|
|
52
57
|
* Calculates text bounds [textWidth, textHeight, lineHeight]
|
|
@@ -80,7 +85,7 @@ export function getTextLines(text) {
|
|
|
80
85
|
* @param {number} y - The y-coordinate of the starting position of the text.
|
|
81
86
|
* @param {CanvasTextProperties} properties - An object containing properties for the text, such as font size, style, and alignment.
|
|
82
87
|
* @returns {void}
|
|
83
|
-
|
|
88
|
+
|
|
84
89
|
*/
|
|
85
90
|
export function drawText(ctx, lines, x, y, properties) {
|
|
86
91
|
ctx.save();
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
4
|
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { PriceAxisType } from '../../components/labels_generator/numeric-axis-labels.generator';
|
|
7
7
|
export declare const isFirefox: boolean;
|
|
8
8
|
/**
|
|
9
9
|
* this function determines whether the event was triggered with the mouse or the touchpad
|
|
@@ -20,11 +20,11 @@ export declare const isFirefox: boolean;
|
|
|
20
20
|
*/
|
|
21
21
|
export declare const touchpadDetector: (e: WheelEvent) => boolean;
|
|
22
22
|
/**
|
|
23
|
-
* this function returns different
|
|
23
|
+
* this function returns different zoom sensitivity for the percent axis and the others
|
|
24
24
|
* @param config
|
|
25
25
|
* @param isTouchpad
|
|
26
26
|
* @returns {number}
|
|
27
27
|
*
|
|
28
28
|
* @doc-tags chart-core, zoom
|
|
29
29
|
*/
|
|
30
|
-
export declare const getTouchpadSensitivity: (
|
|
30
|
+
export declare const getTouchpadSensitivity: (type: PriceAxisType, zoomSensitivity: number) => number;
|
|
@@ -82,15 +82,13 @@ export const touchpadDetector = (e) => {
|
|
|
82
82
|
return isTouchpad;
|
|
83
83
|
};
|
|
84
84
|
/**
|
|
85
|
-
* this function returns different
|
|
85
|
+
* this function returns different zoom sensitivity for the percent axis and the others
|
|
86
86
|
* @param config
|
|
87
87
|
* @param isTouchpad
|
|
88
88
|
* @returns {number}
|
|
89
89
|
*
|
|
90
90
|
* @doc-tags chart-core, zoom
|
|
91
91
|
*/
|
|
92
|
-
export const getTouchpadSensitivity = (
|
|
93
|
-
|
|
94
|
-
const zoomSensitivity = isPercentAxisType ? config.scale.zoomSensitivity / 4 : config.scale.zoomSensitivity;
|
|
95
|
-
return zoomSensitivity;
|
|
92
|
+
export const getTouchpadSensitivity = (type, zoomSensitivity) => {
|
|
93
|
+
return type === 'percent' ? zoomSensitivity / 4 : zoomSensitivity;
|
|
96
94
|
};
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
4
|
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
|
-
export declare const MAX_DECIMAL_DIGITS = 14;
|
|
7
6
|
export type NumberFormatLabels = 'K' | 'M' | 'B';
|
|
8
7
|
export declare class MathUtils {
|
|
9
8
|
static roundToNearest(value: number, precision: number): number;
|
|
@@ -13,6 +12,7 @@ export declare class MathUtils {
|
|
|
13
12
|
static compare(a: number, b: number, eps: number): number;
|
|
14
13
|
static isZero(a: number): boolean;
|
|
15
14
|
static cutNumber(value: number, amountToCut: NumberFormatLabels, zeros?: number): string;
|
|
15
|
+
static isExponential(a: number): boolean;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
18
|
* Checks if first and second number are differs by specified times
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
4
|
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
const MAX_DECIMAL_DIGITS = 14;
|
|
7
7
|
// Array of powers of 10. Used in roundDecimal to walk through mantissa.
|
|
8
8
|
const POW10 = [];
|
|
9
9
|
for (let i = 0; i < MAX_DECIMAL_DIGITS + 1; i++) {
|
|
@@ -75,6 +75,9 @@ export class MathUtils {
|
|
|
75
75
|
};
|
|
76
76
|
return cutMap[amountToCut](value).toFixed(zeros) + amountToCut;
|
|
77
77
|
}
|
|
78
|
+
static isExponential(a) {
|
|
79
|
+
return /\de(\-|\+)\d/.test(a.toString());
|
|
80
|
+
}
|
|
78
81
|
}
|
|
79
82
|
/**
|
|
80
83
|
* Checks if first and second number are differs by specified times
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2019 - 2023 Devexperts Solutions IE Limited
|
|
3
|
+
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
|
+
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getDateTimeFormat(timeZone: string): Intl.DateTimeFormat;
|
|
7
|
+
/**
|
|
8
|
+
* Calulates provided timezone offset.
|
|
9
|
+
* @param timeZone - timezone as IANA string ('Asia/Amman', 'Europe/Amsterdam')
|
|
10
|
+
* @param timestamp - timestamp as number (1701251319717)
|
|
11
|
+
* Returns offset from UTC
|
|
12
|
+
*/
|
|
13
|
+
export declare const getTimezoneOffset: (timeZone: string, timestamp?: number) => number;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2019 - 2023 Devexperts Solutions IE Limited
|
|
3
|
+
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
|
+
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Get a cached Intl.DateTimeFormat instance for the IANA `timeZone`. This can be used
|
|
8
|
+
* to get deterministic local date/time output according to the `en-US` locale which
|
|
9
|
+
* can be used to extract local time parts as necessary.
|
|
10
|
+
* Returns the [year, month, day, hour, minute] tokens of the provided timezone
|
|
11
|
+
*/
|
|
12
|
+
const dateTimeFormatCache = {};
|
|
13
|
+
export function getDateTimeFormat(timeZone) {
|
|
14
|
+
if (!dateTimeFormatCache[timeZone]) {
|
|
15
|
+
// New browsers use `hourCycle`, IE and Chrome <73 does not support it and uses `hour12`
|
|
16
|
+
dateTimeFormatCache[timeZone] = new Intl.DateTimeFormat('en-US', {
|
|
17
|
+
hourCycle: 'h23',
|
|
18
|
+
timeZone,
|
|
19
|
+
year: 'numeric',
|
|
20
|
+
month: 'numeric',
|
|
21
|
+
day: '2-digit',
|
|
22
|
+
hour: '2-digit',
|
|
23
|
+
minute: '2-digit',
|
|
24
|
+
second: '2-digit',
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return dateTimeFormatCache[timeZone];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Calulates provided timezone offset.
|
|
31
|
+
* @param timeZone - timezone as IANA string ('Asia/Amman', 'Europe/Amsterdam')
|
|
32
|
+
* @param timestamp - timestamp as number (1701251319717)
|
|
33
|
+
* Returns offset from UTC
|
|
34
|
+
*/
|
|
35
|
+
export const getTimezoneOffset = (timeZone, timestamp = Date.now()) => {
|
|
36
|
+
const formatter = getDateTimeFormat(timeZone);
|
|
37
|
+
const dateString = formatter.format(timestamp);
|
|
38
|
+
// exec() returns [, fMonth, fDay, fYear, fHour, fMinute]
|
|
39
|
+
const tokens = /(\d+)\/(\d+)\/(\d+),? (\d+):(\d+)/.exec(dateString);
|
|
40
|
+
if (tokens) {
|
|
41
|
+
const asUTC = Date.UTC(+tokens[3], +tokens[1] - 1, +tokens[2], +tokens[4] % 24, +tokens[5], 0);
|
|
42
|
+
let asTimezone = timestamp;
|
|
43
|
+
const over = asTimezone % 1000;
|
|
44
|
+
asTimezone -= over >= 0 ? over : 1000 + over;
|
|
45
|
+
return asUTC - asTimezone;
|
|
46
|
+
}
|
|
47
|
+
return 0;
|
|
48
|
+
};
|