konzen commented on code in PR #21739:
URL: https://github.com/apache/echarts/pull/21739#discussion_r3807451165
##########
src/util/time.ts:
##########
@@ -409,117 +480,545 @@ export function getUnitFromValue(
}
}
-// export function getUnitValue(
-// value: number | Date,
-// unit: TimeUnit,
-// isUTC: boolean
-// ) : number {
-// const date = zrUtil.isNumber(value)
-// ? numberUtil.parseDate(value)
-// : value;
-// unit = unit || getUnitFromValue(value, isUTC);
-
-// switch (unit) {
-// case 'year':
-// return date[fullYearGetterName(isUTC)]();
-// case 'half-year':
-// return date[monthGetterName(isUTC)]() >= 6 ? 1 : 0;
-// case 'quarter':
-// return Math.floor((date[monthGetterName(isUTC)]() + 1) / 4);
-// case 'month':
-// return date[monthGetterName(isUTC)]();
-// case 'day':
-// return date[dateGetterName(isUTC)]();
-// case 'half-day':
-// return date[hoursGetterName(isUTC)]() / 24;
-// case 'hour':
-// return date[hoursGetterName(isUTC)]();
-// case 'minute':
-// return date[minutesGetterName(isUTC)]();
-// case 'second':
-// return date[secondsGetterName(isUTC)]();
-// case 'millisecond':
-// return date[millisecondsGetterName(isUTC)]();
-// }
-// }
-
/**
* e.g.,
* If timeUnit is 'year', return the Jan 1st 00:00:00 000 of that year.
* If timeUnit is 'day', return the 00:00:00 000 of that day.
*
* @return The input date.
*/
-export function roundTime(date: Date, timeUnit: PrimaryTimeUnit, isUTC:
boolean): Date {
- switch (timeUnit) {
- case 'year':
- date[monthSetterName(isUTC)](0);
- case 'month':
- date[dateSetterName(isUTC)](1);
- case 'day':
- date[hoursSetterName(isUTC)](0);
- case 'hour':
- date[minutesSetterName(isUTC)](0);
- case 'minute':
- date[secondsSetterName(isUTC)](0);
- case 'second':
- date[millisecondsSetterName(isUTC)](0);
+export function roundTime(
+ date: Date,
+ timeUnit: PrimaryTimeUnit,
+ timeZone: string
+): Date;
+/**
+ * @deprecated Pass a time zone string instead of the legacy `isUTC` boolean.
+ */
+export function roundTime(
+ date: Date,
+ timeUnit: PrimaryTimeUnit,
+ isUTC: boolean
+): Date;
+export function roundTime(
+ date: Date,
+ timeUnit: PrimaryTimeUnit,
+ timeZoneOrUTC: string | boolean
+): Date {
+ if (__DEV__ && typeof timeZoneOrUTC === 'boolean') {
+ deprecateReplaceLog('isUTC boolean parameter', 'timeZone string
parameter', 'echarts.time.roundTime');
}
+ date.setTime(roundTimeInTimeZone(
+ date.getTime(), timeUnit, normalizeTimeZone(timeZoneOrUTC)
+ ));
return date;
}
+function normalizeTimeZone(timeZoneOrUTC: string | boolean): string {
+ return typeof timeZoneOrUTC === 'string'
+ ? timeZoneOrUTC
+ : timeZoneOrUTC ? 'UTC' : getSystemTimeZone();
+}
+
+/**
+ * @deprecated Use `getTimeZoneParts` to read values in a specific time zone.
+ */
export function fullYearGetterName(isUTC: boolean) {
return isUTC ? 'getUTCFullYear' : 'getFullYear';
}
+/**
+ * @deprecated Use `getTimeZoneParts` to read values in a specific time zone.
+ */
export function monthGetterName(isUTC: boolean) {
return isUTC ? 'getUTCMonth' : 'getMonth';
}
+/**
+ * @deprecated Use `getTimeZoneParts` to read values in a specific time zone.
+ */
export function dateGetterName(isUTC: boolean) {
return isUTC ? 'getUTCDate' : 'getDate';
}
+/**
+ * @deprecated Use `getTimeZoneParts` to read values in a specific time zone.
+ */
export function hoursGetterName(isUTC: boolean) {
return isUTC ? 'getUTCHours' : 'getHours';
}
+/**
+ * @deprecated Use `getTimeZoneParts` to read values in a specific time zone.
+ */
export function minutesGetterName(isUTC: boolean) {
return isUTC ? 'getUTCMinutes' : 'getMinutes';
}
+/**
+ * @deprecated Use `getTimeZoneParts` to read values in a specific time zone.
+ */
export function secondsGetterName(isUTC: boolean) {
return isUTC ? 'getUTCSeconds' : 'getSeconds';
}
+/**
+ * @deprecated Use `getTimeZoneParts` to read values in a specific time zone.
+ */
export function millisecondsGetterName(isUTC: boolean) {
return isUTC ? 'getUTCMilliseconds' : 'getMilliseconds';
}
+/**
+ * @deprecated Use time-zone-aware utilities instead of selecting a local/UTC
`Date` setter.
+ */
export function fullYearSetterName(isUTC: boolean) {
return isUTC ? 'setUTCFullYear' : 'setFullYear';
}
+/**
+ * @deprecated Use time-zone-aware utilities instead of selecting a local/UTC
`Date` setter.
+ */
export function monthSetterName(isUTC: boolean) {
return isUTC ? 'setUTCMonth' : 'setMonth';
}
+/**
+ * @deprecated Use time-zone-aware utilities instead of selecting a local/UTC
`Date` setter.
+ */
export function dateSetterName(isUTC: boolean) {
return isUTC ? 'setUTCDate' : 'setDate';
}
+/**
+ * @deprecated Use time-zone-aware utilities instead of selecting a local/UTC
`Date` setter.
+ */
export function hoursSetterName(isUTC: boolean) {
return isUTC ? 'setUTCHours' : 'setHours';
}
+/**
+ * @deprecated Use time-zone-aware utilities instead of selecting a local/UTC
`Date` setter.
+ */
export function minutesSetterName(isUTC: boolean) {
return isUTC ? 'setUTCMinutes' : 'setMinutes';
}
+/**
+ * @deprecated Use time-zone-aware utilities instead of selecting a local/UTC
`Date` setter.
+ */
export function secondsSetterName(isUTC: boolean) {
return isUTC ? 'setUTCSeconds' : 'setSeconds';
}
+/**
+ * @deprecated Use time-zone-aware utilities instead of selecting a local/UTC
`Date` setter.
+ */
export function millisecondsSetterName(isUTC: boolean) {
return isUTC ? 'setUTCMilliseconds' : 'setMilliseconds';
}
+
+interface TimeZoneDateParts {
+ year: number;
+ // Calendar month, from 1 (January) to 12 (December), matching
Intl/Temporal.
+ month: number;
+ day: number;
+ dayOfWeek: number;
+ hours: number;
+ minutes: number;
+ seconds: number;
+ milliseconds: number;
+ // Same sign as an ISO offset: UTC-05:00 is -300 and UTC+05:30 is 330.
+ offsetMinutes: number;
+}
+
+type TimeZoneWallTimeParts = Omit<TimeZoneDateParts, 'dayOfWeek' |
'offsetMinutes'>;
+
+interface TimeZoneDayInfo {
+ offsetBefore: number;
+ transitionTimestamp?: number;
+ offsetAfter: number;
+}
+
+interface TimeZoneDayCache {
+ dayStartOffsets: zrUtil.HashMap<number, number>;
+ days: zrUtil.HashMap<TimeZoneDayInfo, number>;
+}
+
+// Required for IANA time zones. Legacy environments can provide an Intl
polyfill.
+// eslint-disable-next-line no-restricted-globals
+const intl = Intl;
+type TimeZoneFormatter = ReturnType<typeof intl.DateTimeFormat>;
+type TimeZoneFormatterOptions = NonNullable<Parameters<typeof
intl.DateTimeFormat>[1]>;
+
+const MINUTES_PER_DAY = ONE_DAY / ONE_MINUTE;
+const formatterCache = zrUtil.createHashMap<TimeZoneFormatter, string>();
+const timeZoneDayCaches = zrUtil.createHashMap<TimeZoneDayCache, string>();
Review Comment:
Fixed in 438a10760. Formatters now use a 32-entry LRU, and per-day time-zone
results use a flat 4096-entry LRU. Sequential day calculations still reuse
neighboring cached offsets.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]