|
@@ -54,6 +54,72 @@ export class TimezoneService {
|
|
|
return TimezoneService.instance;
|
|
return TimezoneService.instance;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 将 YYYY-MM-DD 格式的日期转换为指定时区的时间范围(00:00:00 至 23:59:59.999)
|
|
|
|
|
+ * @param dateStr 日期字符串(YYYY-MM-DD)
|
|
|
|
|
+ * @param timeZone 时区(如 'Asia/Shanghai'、'America/New_York')
|
|
|
|
|
+ * @returns 包含 start(UTC 开始时间)和 end(UTC 结束时间)的对象,转换失败返回null
|
|
|
|
|
+ */
|
|
|
|
|
+ public getTimeRangeInTimeZone = (dateStr: string, timeZone: string = "America/Los_Angeles"): { start: Date; end: Date } | null => {
|
|
|
|
|
+ if (!dateStr) return null;
|
|
|
|
|
+
|
|
|
|
|
+ // 解析日期字符串
|
|
|
|
|
+ const [year, month, day] = dateStr.split("-").map(Number);
|
|
|
|
|
+ if (!year || !month || !day || month < 1 || month > 12 || day < 1 || day > 31) {
|
|
|
|
|
+ console.error("Invalid date format. Expected YYYY-MM-DD");
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 1. 在指定时区创建当天00:00:00的日期
|
|
|
|
|
+ // 使用Intl.DateTimeFormat解析指定时区的日期
|
|
|
|
|
+ const formatter = new Intl.DateTimeFormat("en-US", {
|
|
|
|
|
+ timeZone,
|
|
|
|
|
+ year: "numeric",
|
|
|
|
|
+ month: "2-digit",
|
|
|
|
|
+ day: "2-digit",
|
|
|
|
|
+ hour: "2-digit",
|
|
|
|
|
+ minute: "2-digit",
|
|
|
|
|
+ second: "2-digit",
|
|
|
|
|
+ hour12: false,
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 构造指定时区的当天0点字符串
|
|
|
|
|
+ const dateStrInTimeZone = `${year}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")} 00:00:00`;
|
|
|
|
|
+ const parts = formatter.formatToParts(new Date(dateStrInTimeZone));
|
|
|
|
|
+
|
|
|
|
|
+ // 提取指定时区的年月日时分秒
|
|
|
|
|
+ const dateParts: Record<string, number> = {};
|
|
|
|
|
+ parts.forEach((part) => {
|
|
|
|
|
+ if (["year", "month", "day", "hour", "minute", "second"].includes(part.type)) {
|
|
|
|
|
+ dateParts[part.type] = parseInt(part.value, 10);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 计算指定时区的00:00:00对应的UTC时间
|
|
|
|
|
+ const startInTimeZone = new Date(
|
|
|
|
|
+ dateParts.year,
|
|
|
|
|
+ dateParts.month - 1, // 月份从0开始
|
|
|
|
|
+ dateParts.day,
|
|
|
|
|
+ dateParts.hour,
|
|
|
|
|
+ dateParts.minute,
|
|
|
|
|
+ dateParts.second
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 计算指定时区的23:59:59.999对应的UTC时间
|
|
|
|
|
+ const endInTimeZone = new Date(startInTimeZone);
|
|
|
|
|
+ endInTimeZone.setHours(23, 59, 59, 999);
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ start: new Date(startInTimeZone.toISOString()),
|
|
|
|
|
+ end: new Date(endInTimeZone.toISOString()),
|
|
|
|
|
+ };
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error("Error converting date to time zone:", error);
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 根据国家代码获取对应的时区。
|
|
* 根据国家代码获取对应的时区。
|
|
|
* 优先从自定义映射表中查找,如果找不到,则退回到 countries-and-timezones 库的第一个时区。
|
|
* 优先从自定义映射表中查找,如果找不到,则退回到 countries-and-timezones 库的第一个时区。
|