@dative-gpi/foundation-shared-services 1.0.7 → 1.0.10
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/composables/app/useAppTimeZone.ts +90 -201
- package/package.json +3 -3
|
@@ -1,256 +1,145 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { Locale } from "date-fns/locale";
|
|
3
|
-
import { enUS, enGB, fr, it, es, de } from "date-fns/locale";
|
|
1
|
+
import { addMilliseconds, format, parse, subDays } from "date-fns";
|
|
4
2
|
import { computed, ref } from "vue";
|
|
5
3
|
|
|
6
4
|
import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui/composables";
|
|
7
|
-
import
|
|
8
|
-
import { isoTimeFormat } from "@dative-gpi/foundation-shared-domain/tools";
|
|
5
|
+
import { ISO_FORMAT, OPTIONS } from "@dative-gpi/foundation-shared-domain/tools";
|
|
9
6
|
|
|
10
7
|
import { useAppLanguageCode } from "./useAppLanguageCode";
|
|
11
8
|
|
|
12
|
-
const timeZone = ref<
|
|
9
|
+
const timeZone = ref<string | undefined>(undefined);
|
|
13
10
|
|
|
14
11
|
export const useAppTimeZone = () => {
|
|
15
|
-
const
|
|
12
|
+
const { $tr } = useTranslationsProvider();
|
|
13
|
+
|
|
14
|
+
const setAppTimeZone = (payload: string) => {
|
|
16
15
|
timeZone.value = payload;
|
|
17
16
|
};
|
|
18
17
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
case "utc-11:00:00": offset = -11; break;
|
|
23
|
-
case "utc-10:00:00": offset = -10; break;
|
|
24
|
-
case "utc-09:00:00": offset = -9; break;
|
|
25
|
-
case "utc-08:00:00": offset = -8; break;
|
|
26
|
-
case "utc-07:00:00": offset = -7; break;
|
|
27
|
-
case "utc-06:00:00": offset = -6; break;
|
|
28
|
-
case "utc-05:00:00": offset = -5; break;
|
|
29
|
-
case "utc-04:00:00": offset = -4; break;
|
|
30
|
-
case "utc-03:00:00": offset = -3; break;
|
|
31
|
-
case "utc-02:00:00": offset = -2; break;
|
|
32
|
-
case "utc-01:00:00": offset = -1; break;
|
|
33
|
-
case "utc+01:00:00": offset = +1; break;
|
|
34
|
-
case "utc+02:00:00": offset = +2; break;
|
|
35
|
-
case "utc+03:00:00": offset = +3; break;
|
|
36
|
-
case "utc+04:00:00": offset = +4; break;
|
|
37
|
-
case "utc+05:00:00": offset = +5; break;
|
|
38
|
-
case "utc+06:00:00": offset = +6; break;
|
|
39
|
-
case "utc+07:00:00": offset = +7; break;
|
|
40
|
-
case "utc+08:00:00": offset = +8; break;
|
|
41
|
-
case "utc+09:00:00": offset = +9; break;
|
|
42
|
-
case "utc+10:00:00": offset = +10; break;
|
|
43
|
-
case "utc+11:00:00": offset = +11; break;
|
|
44
|
-
case "utc+12:00:00": offset = +12; break;
|
|
45
|
-
case "utc+13:00:00": offset = +13; break;
|
|
46
|
-
case "utc+14:00:00": offset = +14; break;
|
|
18
|
+
const epochToShortDateFormat = (value: number | null | undefined): string => {
|
|
19
|
+
if (value == null || !isFinite(value)) {
|
|
20
|
+
return "";
|
|
47
21
|
}
|
|
48
|
-
|
|
22
|
+
const date = new Date(value);
|
|
23
|
+
return date.toLocaleString(useAppLanguageCode().languageCode.value, { ...OPTIONS.shortDate, timeZone: timeZone.value });
|
|
49
24
|
};
|
|
50
25
|
|
|
51
|
-
const
|
|
52
|
-
|
|
26
|
+
const epochToLongDateFormat = (value: number | null | undefined): string => {
|
|
27
|
+
if (value == null || !isFinite(value)) {
|
|
28
|
+
return "";
|
|
29
|
+
}
|
|
30
|
+
const date = new Date(value);
|
|
31
|
+
const now = new Date();
|
|
32
|
+
if (date.toLocaleString(useAppLanguageCode().languageCode.value, { ...OPTIONS.shortDate, timeZone: timeZone.value }) === now.toLocaleString(useAppLanguageCode().languageCode.value, { ...OPTIONS.shortDate, timeZone: timeZone.value })) {
|
|
33
|
+
return $tr("ui.time-zone.today", "Today");
|
|
34
|
+
}
|
|
35
|
+
if (date.toLocaleString(useAppLanguageCode().languageCode.value, { ...OPTIONS.shortDate, timeZone: timeZone.value }) === subDays(now, 1).toLocaleString(useAppLanguageCode().languageCode.value, { ...OPTIONS.shortDate, timeZone: timeZone.value })) {
|
|
36
|
+
return $tr("ui.time-zone.yesterday", "Yesterday");
|
|
37
|
+
}
|
|
38
|
+
const dateString = date.toLocaleString(useAppLanguageCode().languageCode.value, { ...OPTIONS.longDate, timeZone: timeZone.value });
|
|
39
|
+
return dateString[0].toLocaleUpperCase() + dateString.slice(1);
|
|
53
40
|
};
|
|
54
41
|
|
|
55
|
-
const
|
|
56
|
-
|
|
42
|
+
const epochToShortTimeFormat = (value: number | null | undefined): string => {
|
|
43
|
+
if (value == null || !isFinite(value)) {
|
|
44
|
+
return "";
|
|
45
|
+
}
|
|
46
|
+
const date = new Date(value);
|
|
47
|
+
return date.toLocaleString(useAppLanguageCode().languageCode.value, { ...OPTIONS.shortTime, timeZone: timeZone.value });
|
|
57
48
|
};
|
|
58
49
|
|
|
59
|
-
const
|
|
60
|
-
|
|
50
|
+
const epochToLongTimeFormat = (value: number | null | undefined): string => {
|
|
51
|
+
if (value == null || !isFinite(value)) {
|
|
52
|
+
return "";
|
|
53
|
+
}
|
|
54
|
+
const date = new Date(value);
|
|
55
|
+
const now = new Date();
|
|
56
|
+
if (date.toLocaleString(useAppLanguageCode().languageCode.value, { ...OPTIONS.shortDate, timeZone: timeZone.value }) === now.toLocaleString(useAppLanguageCode().languageCode.value, { ...OPTIONS.shortDate, timeZone: timeZone.value })) {
|
|
57
|
+
return `${$tr("ui.time-zone.today-at", "Today at")} ${date.toLocaleString(useAppLanguageCode().languageCode.value, { ...OPTIONS.time, timeZone: timeZone.value })}`;
|
|
58
|
+
}
|
|
59
|
+
if (date.toLocaleString(useAppLanguageCode().languageCode.value, { ...OPTIONS.shortDate, timeZone: timeZone.value }) === subDays(now, 1).toLocaleString(useAppLanguageCode().languageCode.value, { ...OPTIONS.shortDate, timeZone: timeZone.value })) {
|
|
60
|
+
return `${$tr("ui.time-zone.yesterday-at", "Yesterday at")} ${date.toLocaleString(useAppLanguageCode().languageCode.value, { ...OPTIONS.time, timeZone: timeZone.value })}`;
|
|
61
|
+
}
|
|
62
|
+
const dateString = date.toLocaleString(useAppLanguageCode().languageCode.value, { ...OPTIONS.longTime, timeZone: timeZone.value });
|
|
63
|
+
return dateString[0].toLocaleUpperCase() + dateString.slice(1);
|
|
61
64
|
};
|
|
62
65
|
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (matchData) {
|
|
67
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
68
|
-
const [_, sign, hour, minute] = matchData;
|
|
69
|
-
return parseInt(sign + "1") * ((hour ? parseInt(hour) : 0) * 60 + (minute ? parseInt(minute) : 0)) * 60 * 1000;
|
|
66
|
+
const epochToTimeOnlyFormat = (value: number | null | undefined): string => {
|
|
67
|
+
if (value == null || !isFinite(value)) {
|
|
68
|
+
return "";
|
|
70
69
|
}
|
|
71
|
-
|
|
70
|
+
const date = new Date(value);
|
|
71
|
+
return date.toLocaleString(useAppLanguageCode().languageCode.value, { ...OPTIONS.time, timeZone: timeZone.value });
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}).formatToParts().
|
|
79
|
-
|
|
80
|
-
const offset = timeZoneName.slice(3);
|
|
81
|
-
if (!offset) {
|
|
82
|
-
return "UTC +00:00:00";
|
|
83
|
-
}
|
|
84
|
-
const matchData = offset.match(/([+-])(\d+)(?::(\d+))?/);
|
|
85
|
-
if (matchData) {
|
|
86
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
87
|
-
const [_, sign, hour, minute] = matchData;
|
|
88
|
-
return `UTC ${sign}${hour.padStart(2, "0")}:${(minute ?? "").padStart(2, "0")}:00`;
|
|
89
|
-
}
|
|
90
|
-
return "UTC +00:00:00";
|
|
74
|
+
const getOffsetUser = (): number => {
|
|
75
|
+
const offsetParts = (Intl.DateTimeFormat(undefined, {
|
|
76
|
+
timeZone: timeZone.value,
|
|
77
|
+
timeZoneName: "longOffset"
|
|
78
|
+
}).formatToParts(new Date).pop()?.value.slice(3) || "+00:00").split(':');
|
|
79
|
+
return (parseInt(offsetParts[0]) * 60 + parseInt(offsetParts[1])) * 60 * 1000;
|
|
91
80
|
};
|
|
92
81
|
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}).formatToParts().
|
|
82
|
+
const getOffsetMachine = (): number => {
|
|
83
|
+
const offsetParts = (Intl.DateTimeFormat(undefined, {
|
|
84
|
+
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
85
|
+
timeZoneName: "longOffset"
|
|
86
|
+
}).formatToParts(new Date).pop()?.value.slice(3) || "+00:00").split(':');
|
|
87
|
+
return (parseInt(offsetParts[0]) * 60 + parseInt(offsetParts[1])) * 60 * 1000;
|
|
88
|
+
};
|
|
98
89
|
|
|
99
|
-
|
|
100
|
-
if (
|
|
90
|
+
const getOffsetDifference = (): number => {
|
|
91
|
+
if (timeZone.value == null) {
|
|
101
92
|
return 0;
|
|
102
93
|
}
|
|
103
|
-
|
|
104
|
-
if (matchData) {
|
|
105
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
106
|
-
const [_, sign, hour, minute] = matchData;
|
|
107
|
-
return parseInt(sign + "1") * ((hour ? parseInt(hour) : 0) * 60 + (minute ? parseInt(minute) : 0)) * 60 * 1000;
|
|
108
|
-
}
|
|
109
|
-
return 0;
|
|
94
|
+
return getOffsetUser() - getOffsetMachine();
|
|
110
95
|
};
|
|
111
96
|
|
|
112
|
-
const todayToEpoch = (
|
|
113
|
-
|
|
114
|
-
if (resetHours) {
|
|
115
|
-
today.setHours(0, 0, 0, 0);
|
|
116
|
-
}
|
|
117
|
-
return today.getTime() + getMachineOffsetMillis() - getUserOffsetMillis();
|
|
97
|
+
const todayToEpoch = (): number => {
|
|
98
|
+
return (new Date().getTime() + getOffsetDifference());
|
|
118
99
|
};
|
|
119
100
|
|
|
120
101
|
const pickerToEpoch = (value: Date | null | undefined): number => {
|
|
121
102
|
if (value != null) {
|
|
122
|
-
|
|
123
|
-
return value.getTime() + getMachineOffsetMillis() - getUserOffsetMillis();
|
|
103
|
+
return value.getTime() - getOffsetDifference();
|
|
124
104
|
}
|
|
125
105
|
return 0;
|
|
126
106
|
};
|
|
127
107
|
|
|
128
108
|
const epochToPicker = (value: number | null | undefined): Date => {
|
|
129
|
-
const date = new Date(0);
|
|
130
109
|
if (value != null) {
|
|
131
|
-
|
|
132
|
-
date.setUTCMilliseconds(value - getMachineOffsetMillis() + getUserOffsetMillis());
|
|
110
|
+
return new Date(value + getOffsetDifference());
|
|
133
111
|
}
|
|
134
|
-
return
|
|
112
|
+
return new Date(0);
|
|
135
113
|
};
|
|
136
114
|
|
|
137
115
|
const epochToPickerHeader = (value: number): { d: number, m: number, y: number } => {
|
|
138
|
-
const date =
|
|
139
|
-
if (value != null) {
|
|
140
|
-
date.setUTCMilliseconds(value - getMachineOffsetMillis() + getUserOffsetMillis());
|
|
141
|
-
}
|
|
116
|
+
const date = epochToPicker(value);
|
|
142
117
|
return { d: date.getDate(), m: date.getMonth(), y: date.getFullYear() };
|
|
143
118
|
};
|
|
144
119
|
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const date = new Date(0);
|
|
150
|
-
date.setUTCMilliseconds(value - getMachineOffsetMillis() + getUserOffsetMillis());
|
|
151
|
-
return format(date, "EEEE dd LLLL yyyy", { locale: getLocale() });
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
const epochToLongTimeFormat = (value: number | null | undefined): string => {
|
|
155
|
-
if (value == null || !isFinite(value)) {
|
|
156
|
-
return "";
|
|
157
|
-
}
|
|
158
|
-
const date = new Date(0);
|
|
159
|
-
date.setUTCMilliseconds(value - getMachineOffsetMillis() + getUserOffsetMillis());
|
|
160
|
-
return format(date, overrideFormat(date, "EEEE dd LLLL yyyy HH:mm"), { locale: getLocale() })
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
const epochToShortDateFormat = (value: number | null | undefined): string => {
|
|
164
|
-
if (value == null || !isFinite(value)) {
|
|
165
|
-
return "";
|
|
166
|
-
}
|
|
167
|
-
const date = new Date(0);
|
|
168
|
-
date.setUTCMilliseconds(value - getMachineOffsetMillis() + getUserOffsetMillis());
|
|
169
|
-
switch (getLocale()) {
|
|
170
|
-
case enUS: {
|
|
171
|
-
return format(date, "MM/dd/yyyy", { locale: getLocale() });
|
|
172
|
-
}
|
|
173
|
-
default: {
|
|
174
|
-
return format(date, "dd/MM/yyyy", { locale: getLocale() });
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
const epochToTimeOnlyFormat = (value: number | null | undefined): string => {
|
|
180
|
-
if (value == null || !isFinite(value)) {
|
|
181
|
-
return "";
|
|
182
|
-
}
|
|
183
|
-
const date = new Date(0);
|
|
184
|
-
date.setUTCMilliseconds(value - getMachineOffsetMillis() + getUserOffsetMillis());
|
|
185
|
-
return format(date, "HH:mm:ss", { locale: getLocale() });
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
const epochToShortTimeFormat = (value: number | null | undefined): string => {
|
|
189
|
-
if (value == null || !isFinite(value)) {
|
|
190
|
-
return "";
|
|
191
|
-
}
|
|
192
|
-
const date = new Date(0);
|
|
193
|
-
date.setUTCMilliseconds(value - getMachineOffsetMillis() + getUserOffsetMillis());
|
|
194
|
-
switch (getLocale()) {
|
|
195
|
-
case enUS: {
|
|
196
|
-
return format(date, "MM/dd/yyyy HH:mm", { locale: getLocale() });
|
|
197
|
-
}
|
|
198
|
-
default: {
|
|
199
|
-
return format(date, "dd/MM/yyyy HH:mm", { locale: getLocale() });
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
const todayTimeFormat = (): string => {
|
|
205
|
-
return `'${useTranslationsProvider().$tr("ui.time-zone.today-at", "Today at").replace(/'/g, "''")}' HH:mm:ss`;
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
const yesterdayTimeFormat = (): string => {
|
|
209
|
-
return `'${useTranslationsProvider().$tr("ui.time-zone.yesterday-at", "Yesterday at").replace(/'/g, "''")}' HH:mm:ss`;
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
const overrideFormat = (date: Date, askedFormat: string): string => {
|
|
213
|
-
const now = new Date();
|
|
214
|
-
if (date.toDateString() === now.toDateString()) {
|
|
215
|
-
return todayTimeFormat();
|
|
216
|
-
}
|
|
217
|
-
if (date.toDateString() === subDays(now, 1).toDateString()) {
|
|
218
|
-
return yesterdayTimeFormat();
|
|
219
|
-
}
|
|
220
|
-
return askedFormat;
|
|
120
|
+
const todayToPicker = (): string => {
|
|
121
|
+
const date = addMilliseconds(new Date(), -getOffsetMachine());
|
|
122
|
+
date.setSeconds(0, 0);
|
|
123
|
+
return format(date, ISO_FORMAT);
|
|
221
124
|
};
|
|
222
125
|
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
case "it-IT": return it;
|
|
228
|
-
case "en-GB": return enGB;
|
|
229
|
-
case "de-DE": return de;
|
|
230
|
-
default: return enUS;
|
|
231
|
-
}
|
|
126
|
+
const yesterdayToPicker = (): string => {
|
|
127
|
+
const date = addMilliseconds(subDays(new Date(), 1), -getOffsetMachine());
|
|
128
|
+
date.setSeconds(0, 0);
|
|
129
|
+
return format(date, ISO_FORMAT);
|
|
232
130
|
};
|
|
233
131
|
|
|
234
|
-
const parseForPicker = (value: string, dateFormat: string =
|
|
235
|
-
|
|
236
|
-
date = addMilliseconds(date, userOffset());
|
|
132
|
+
const parseForPicker = (value: string, dateFormat: string = ISO_FORMAT): number | null => {
|
|
133
|
+
const date = addMilliseconds(parse(value, dateFormat, new Date()), getOffsetUser());
|
|
237
134
|
if (!isFinite(date.getTime())) {
|
|
238
135
|
return null;
|
|
239
136
|
}
|
|
240
137
|
return date.getTime();
|
|
241
138
|
};
|
|
242
139
|
|
|
243
|
-
const formatCurrentForPicker = (daysOffset: number = -1): string => {
|
|
244
|
-
let date = new Date();
|
|
245
|
-
date.setSeconds(0, 0);
|
|
246
|
-
date = addMilliseconds(addDays(date, daysOffset), -machineOffset());
|
|
247
|
-
return format(date, isoTimeFormat());
|
|
248
|
-
};
|
|
249
|
-
|
|
250
140
|
const formatFromPicker = (date: number | null): string => {
|
|
251
141
|
if (date != null) {
|
|
252
|
-
|
|
253
|
-
return format(epoch, isoTimeFormat());
|
|
142
|
+
return format(date - getOffsetMachine(), ISO_FORMAT);
|
|
254
143
|
}
|
|
255
144
|
return "";
|
|
256
145
|
};
|
|
@@ -259,7 +148,7 @@ export const useAppTimeZone = () => {
|
|
|
259
148
|
if (epoch == null || !isFinite(epoch)) {
|
|
260
149
|
return "";
|
|
261
150
|
}
|
|
262
|
-
return format(epoch
|
|
151
|
+
return format(epoch, ISO_FORMAT);
|
|
263
152
|
};
|
|
264
153
|
|
|
265
154
|
const ready = computed(() => timeZone.value !== null);
|
|
@@ -268,10 +157,6 @@ export const useAppTimeZone = () => {
|
|
|
268
157
|
ready,
|
|
269
158
|
timeZone,
|
|
270
159
|
setAppTimeZone,
|
|
271
|
-
getUserOffset,
|
|
272
|
-
getMachineOffset,
|
|
273
|
-
getUserOffsetMillis,
|
|
274
|
-
getMachineOffsetMillis,
|
|
275
160
|
todayToEpoch,
|
|
276
161
|
pickerToEpoch,
|
|
277
162
|
epochToPicker,
|
|
@@ -282,8 +167,12 @@ export const useAppTimeZone = () => {
|
|
|
282
167
|
epochToShortTimeFormat,
|
|
283
168
|
epochToTimeOnlyFormat,
|
|
284
169
|
parseForPicker,
|
|
285
|
-
|
|
170
|
+
todayToPicker,
|
|
171
|
+
yesterdayToPicker,
|
|
286
172
|
formatFromPicker,
|
|
287
|
-
formatEpochToVariable
|
|
173
|
+
formatEpochToVariable,
|
|
174
|
+
getOffsetUser,
|
|
175
|
+
getOffsetMachine,
|
|
176
|
+
getOffsetDifference
|
|
288
177
|
};
|
|
289
178
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dative-gpi/foundation-shared-services",
|
|
3
3
|
"sideEffects": false,
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.10",
|
|
5
5
|
"description": "",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"author": "",
|
|
11
11
|
"license": "ISC",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@dative-gpi/foundation-shared-domain": "1.0.
|
|
13
|
+
"@dative-gpi/foundation-shared-domain": "1.0.10"
|
|
14
14
|
},
|
|
15
15
|
"peerDependencies": {
|
|
16
16
|
"@dative-gpi/bones-ui": "^0.0.75",
|
|
@@ -18,5 +18,5 @@
|
|
|
18
18
|
"vue": "^3.4.29",
|
|
19
19
|
"vue-router": "^4.3.0"
|
|
20
20
|
},
|
|
21
|
-
"gitHead": "
|
|
21
|
+
"gitHead": "018a67489fc022344c90d45b02bfabdcd0dcefec"
|
|
22
22
|
}
|