> 技术文档 > 鸿蒙NEXT开发日期工具类DateUtil(ArkTs)_arkts 时间格式化

鸿蒙NEXT开发日期工具类DateUtil(ArkTs)_arkts 时间格式化

import { i18n, intl } from \'@kit.LocalizationKit\';
import { NumberUtil } from \'./NumberUtil\';

export const DATE_FORMAT1: string = \"yyyy-MM-dd HH:mm:ss\"; // 2025-01-05 14:06:55
export const DATE_FORMAT4: string = \"yyyy-MM-dd\"; // 2025-01-05

/**
 * 日期工具类
 *
 * 提供一组静态方法,用于处理和操作日期类型的数据。
 * 包括日期格式化、解析、转换等功能。
 *
 * @author CSDN-鸿蒙布道师
 * @since 2025/04/03
 */
export class DateUtil {

  /**
   * 获取格式化日期,将传入的日期格式化为 Date 对象。
   *
   * 支持以下输入类型:
   * - 无参数:返回当前时间的 Date 对象。
   * - 字符串:支持多种日期格式(如 \"2025-01-05\" 或 \"2025-01-05 14:06:55\")。
   * - 时间戳:支持 10 位或 13 位时间戳。
   * - Date 对象:直接返回。
   *
   * @param date 输入的日期参数(可选)
   * @returns 格式化后的 Date 对象
   */
  static getFormatDate(date?: number | string | Date): Date {
    if (!date) {
      // 如果未提供参数或参数为空,则返回当前时间
      return new Date();
    }

    if (typeof date === \"string\") {
      // 处理字符串日期
      if (date.trim().length === 0) {
        return new Date(); // 空字符串返回当前时间
      }

      // 尝试解析时间戳
      const timestamp = NumberUtil.toInt(date);
      if (timestamp > 0) {
        return new Date(timestamp * (date.length === 10 ? 1000 : 1)); // 转换为毫秒级时间戳
      }

      // 标准化日期字符串格式
      let normalizedDate = date
        .replace(/[-年月日]/g, \'/\') // 替换分隔符
        .replace(/[:时分秒]/g, \':\') // 替换时间分隔符
        .replace(/\\s+/g, \' \') // 去除多余空格
        .trim();

      // 补齐时间部分(如 \"2025-01-05 14\" -> \"2025-01-05 14:00:00\")
      if (normalizedDate.split(\' \').length === 2 && !normalizedDate.includes(\':\')) {
        normalizedDate += \':00:00\';
      }

      try {
        return new Date(normalizedDate); // 尝试解析标准化后的日期字符串
      } catch {
        throw new Error(`Invalid date string: ${date}`);
      }
    }

    if (typeof date === \"number\") {
      // 处理时间戳
      const timestamp = date * (date.toString().length === 10 ? 1000 : 1); // 转换为毫秒级时间戳
      return new Date(timestamp);
    }

    // 如果是 Date 对象,直接返回
    return new Date(date);
  }

  /**
   * 获取格式化日期,将传入的日期格式化为指定格式的字符串
   *
   * 支持自定义格式化模板,例如:
   * - \"yyyy-MM-dd HH:mm:ss\" -> \"2025-01-05 14:06:55\"
   * - \"yyyy/MM/dd HH:mm\" -> \"2025/01/05 14:06\"
   * - \"HH:mm:ss.fff\" -> \"14:06:55.123\"
   *
   * @param date 输入的日期参数(支持时间戳、字符串或 Date 对象)
   * @param format 格式化字符串,默认为 \"yyyy-MM-dd HH:mm:ss\"
   * @returns 格式化后的日期字符串
   */
  static getFormatDateStr(date: number | string | Date, format: string = DATE_FORMAT1): string {
    // 将输入日期标准化为 Date 对象
    const normalizedDate = DateUtil.getFormatDate(date);

    // 定义格式化占位符及其对应的值
    const formatMap = {
      yyyy: normalizedDate.getFullYear().toString(), // 年份
      MM: DateUtil.padZero(normalizedDate.getMonth() + 1), // 月份 (0-11)
      dd: DateUtil.padZero(normalizedDate.getDate()), // 日期 (1-31)
      HH: DateUtil.padZero(normalizedDate.getHours()), // 小时 (0-23)
      mm: DateUtil.padZero(normalizedDate.getMinutes()), // 分钟 (0-59)
      ss: DateUtil.padZero(normalizedDate.getSeconds()), // 秒数 (0-59)
      fff: normalizedDate.getMilliseconds().toString().padStart(3, \'0\'), // 毫秒 (0-999)
    };

    // 替换格式化字符串中的占位符
    return Object.keys(formatMap).reduce((formatted, placeholder) => {
      const value = (formatMap as Record)[placeholder];
      return formatted.replace(new RegExp(placeholder, \'g\'), value);
    }, format);
  }

  /**
   * 获取今天的日期
   * @returns 当前日期的 Date 对象
   */
  static getToday(): Date {
    return new Date();
  }

  /**
   * 获取今天的时间戳
   * @returns 当前时间的时间戳(毫秒)
   */
  static getTodayTime(): number {
    return Date.now(); // 使用 Date.now() 替代 new Date().getTime(),性能更高
  }

  /**
   * 获取今天的时间,字符串类型
   * @param format 格式化字符串,默认为 \"yyyy-MM-dd HH:mm:ss\"
   * @returns 格式化后的日期字符串
   */
  static getTodayStr(format: string = DATE_FORMAT1): string {
    return DateUtil.getFormatDateStr(new Date(), format);
  }

  /**
   * 判断日期是否是今天
   * @param date 输入日期(支持时间戳、字符串或 Date 对象)
   * @returns 如果是今天,则返回 true;否则返回 false
   */
  static isToday(date: number | string | Date): boolean {
    const today = DateUtil.getTodayStr(DATE_FORMAT4); // yyyy-MM-dd
    const inputDate = DateUtil.getFormatDateStr(date, DATE_FORMAT4);
    return today === inputDate;
  }

  /**
   * 获取当前年份
   * @returns 当前年份
   */
  static getNowYear(): number {
    return new Date().getFullYear();
  }

  /**
   * 获取当前月份(1-12)
   * @returns 当前月份
   */
  static getNowMonth(): number {
    return new Date().getMonth() + 1; // 月份从 0 开始,需要加 1
  }

  /**
   * 获取当前日
   * @returns 当前日期
   */
  static getNowDay(): number {
    return new Date().getDate();
  }

  /**
   * 判断是否是闰年
   * @param year 不传时默认为当前年
   * @returns 如果是闰年,则返回 true;否则返回 false
   */
  static isLeapYear(year: number | Date = new Date()): boolean {
    year = year instanceof Date ? year.getFullYear() : year;
    return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
  }

  /**
   * 获取指定年份的天数
   * @param year 指定年份
   * @returns 该年份的天数(365 或 366)
   */
  static getDaysByYear(year: number): number {
    return DateUtil.isLeapYear(year) ? 366 : 365;
  }

  /**
   * 获取指定月份的天数
   * @param year 指定年份
   * @param month 指定月份(1-12)
   * @returns 该月份的天数
   */
  static getDaysByMonth(year: number, month: number): number {
    if (month === 2) {
      return DateUtil.isLeapYear(year) ? 29 : 28;
    }
    return [4, 6, 9, 11].includes(month) ? 30 : 31;
  }

  /**
   * 判断两个日期是否是同一年
   * @param date1 第一个日期
   * @param date2 第二个日期
   * @returns 如果是同一年,则返回 true;否则返回 false
   */
  static isSameYear(date1: number | string | Date, date2: number | string | Date): boolean {
    const d1 = DateUtil.getFormatDate(date1);
    const d2 = DateUtil.getFormatDate(date2);
    return d1.getFullYear() === d2.getFullYear();
  }

  /**
   * 判断两个日期是否是同一月
   * @param date1 第一个日期
   * @param date2 第二个日期
   * @returns 如果是同一月,则返回 true;否则返回 false
   */
  static isSameMonth(date1: number | string | Date, date2: number | string | Date): boolean {
    const d1 = DateUtil.getFormatDate(date1);
    const d2 = DateUtil.getFormatDate(date2);
    return d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth();
  }

  /**
   * 判断两个日期是否是同一周
   * @param date1 第一个日期
   * @param date2 第二个日期
   * @returns 如果是同一周,则返回 true;否则返回 false
   */
  static isSameWeek(date1: number | string | Date, date2: number | string | Date): boolean {
    const oneDayTime = 1000 * 60 * 60 * 24; // 一天的毫秒数
    const dayCount1 = Math.floor(DateUtil.getFormatDate(date1).getTime() / oneDayTime);
    const dayCount2 = Math.floor(DateUtil.getFormatDate(date2).getTime() / oneDayTime);
    const weekIndex1 = Math.floor((dayCount1 + 4) / 7);
    const weekIndex2 = Math.floor((dayCount2 + 4) / 7);
    return weekIndex1 === weekIndex2;
  }

  /**
   * 判断两个日期是否是同一天
   * @param date1 第一个日期
   * @param date2 第二个日期
   * @returns 如果是同一天,则返回 true;否则返回 false
   */
  static isSameDay(date1: number | string | Date, date2: number | string | Date): boolean {
    const d1 = DateUtil.getFormatDate(date1);
    const d2 = DateUtil.getFormatDate(date2);
    return (
      d1.getFullYear() === d2.getFullYear() &&
        d1.getMonth() === d2.getMonth() &&
        d1.getDate() === d2.getDate()
    );
  }

  /**
   * 获取日历对象,并设置日历对象内部的时间日期
   * @param date 输入日期(支持时间戳、字符串或 Date 对象)
   * @param type 合法的日历类型,默认为区域默认的日历类型
   * @param locale 合法的语言环境值,默认为 \"zh-Hans\"
   * @returns 日历对象
   */
  static getCalendar(
    date?: number | string | Date,
    type: string = \"gregory\",
    locale: string = \"zh-Hans\"
  ): i18n.Calendar {
    const normalizedDate = DateUtil.getFormatDate(date);
    const calendar = i18n.getCalendar(locale, type);
    calendar.setTime(normalizedDate);
    return calendar;
  }

  /**
   * 获取日历对象中与 field 相关联的值
   * @param field 指定字段
   * @param date 输入日期(支持时间戳、字符串或 Date 对象)
   * @param type 合法的日历类型,默认为区域默认的日历类型
   * @param locale 合法的语言环境值,默认为 \"zh-Hans\"
   * @returns 字段的值
   */
  static getCalendarField(
    field: string,
    date?: number | string | Date,
    type: string = \"gregory\",
    locale: string = \"zh-Hans\"
  ): number {
    const normalizedDate = DateUtil.getFormatDate(date);
    const calendar = i18n.getCalendar(locale, type);
    calendar.setTime(normalizedDate);
    return calendar.get(field);
  }

  /**
   * 在日历的给定字段进行加减操作
   * @param date 输入日期(支持时间戳、字符串或 Date 对象)
   * @param field 指定字段
   * @param amount 加减值
   * @param type 合法的日历类型,默认为区域默认的日历类型
   * @param locale 合法的语言环境值,默认为 \"zh-Hans\"
   * @returns 修改后的日期
   */
  static getCalendarAdd(
    date: number | string | Date,
    field: string,
    amount: number,
    type: string = \"gregory\",
    locale: string = \"zh-Hans\"
  ): Date {
    const normalizedDate = DateUtil.getFormatDate(date);
    const calendar = i18n.getCalendar(locale, type);
    calendar.setTime(normalizedDate);
    calendar.add(field, amount);
    return new Date(calendar.getTimeInMillis());
  }

  /**
   * 判断指定的日期在日历中是否为周末
   * @param date 输入日期(支持时间戳、字符串或 Date 对象)
   * @returns 如果是周末,则返回 true;否则返回 false
   */
  static isWeekend(date?: number | string | Date): boolean {
    const normalizedDate = DateUtil.getFormatDate(date);
    const calendar = i18n.getCalendar(\"zh-Hans\");
    calendar.setTime(normalizedDate);
    return calendar.isWeekend(normalizedDate);
  }

  /**
   * 比较日历和指定日期相差的天数(按毫秒级的精度,不足一天将按一天进行计算)。
   * 正数代表日历时间更早,负数代表日历时间更晚。
   * @param date1 第一个日期
   * @param date2 第二个日期
   * @returns 相差的天数
   */
  static compareDays(date1: number | string | Date, date2: number | string | Date): number {
    const d1 = DateUtil.getFormatDate(date1).getTime();
    const d2 = DateUtil.getFormatDate(date2).getTime();
    const diffMs = d2 - d1; // 时间差(毫秒)
    return Math.ceil(diffMs / (1000 * 60 * 60 * 24)); // 转换为天数,向上取整
  }

  /**
   * 比较两个日期相差的毫秒数
   * @param date1 第一个日期
   * @param date2 第二个日期
   * @param floor 是否向下取整,默认 false
   * @returns 相差的毫秒数
   */
  static compareDate(date1: number | string | Date, date2: number | string | Date, floor: boolean = false): number {
    const diff = DateUtil.getFormatDate(date2).getTime() - DateUtil.getFormatDate(date1).getTime();
    return floor ? Math.floor(diff) : diff;
  }

  /**
   * 获取前几天或后几天的日期
   * @param date 输入日期
   * @param amount 偏移天数(正数表示后几天,负数表示前几天)
   * @returns 新的日期对象
   */
  static getAmountDay(date: number | string | Date, amount: number): Date {
    return DateUtil.getCalendarAdd(date, \"date\", amount);
  }

  /**
   * 获取前几天或后几天的日期,返回字符串
   * @param date 输入日期
   * @param amount 偏移天数(正数表示后几天,负数表示前几天)
   * @param format 格式化字符串,默认 \"yyyy-MM-dd\"
   * @returns 格式化后的日期字符串
   */
  static getAmountDayStr(date: number | string | Date, amount: number, format: string = DATE_FORMAT4): string {
    return DateUtil.getFormatDateStr(DateUtil.getAmountDay(date, amount), format);
  }

  /**
   * 获取前一天的日期
   * @param date 输入日期
   * @returns 新的日期对象
   */
  static getBeforeDay(date: number | string | Date): Date {
    return DateUtil.getAmountDay(date, -1);
  }

  /**
   * 获取前一天的日期,返回字符串
   * @param date 输入日期
   * @param format 格式化字符串,默认 \"yyyy-MM-dd\"
   * @returns 格式化后的日期字符串
   */
  static getBeforeDayStr(date: number | string | Date, format: string = DATE_FORMAT4): string {
    return DateUtil.getAmountDayStr(date, -1, format);
  }

  /**
   * 获取后一天的日期
   * @param date 输入日期
   * @returns 新的日期对象
   */
  static getAfterDay(date: number | string | Date): Date {
    return DateUtil.getAmountDay(date, 1);
  }

  /**
   * 获取后一天的日期,返回字符串
   * @param date 输入日期
   * @param format 格式化字符串,默认 \"yyyy-MM-dd\"
   * @returns 格式化后的日期字符串
   */
  static getAfterDayStr(date: number | string | Date, format: string = DATE_FORMAT4): string {
    return DateUtil.getAmountDayStr(date, 1, format);
  }

  /**
   * 获取给定日期是当月的第几周
   * @param date 输入日期
   * @returns 当月的第几周
   */
  static getWeekOfMonth(date: number | string | Date): number {
    return DateUtil.getCalendarField(\"week_of_month\", date);
  }

  /**
   * 获取给定日期是星期几
   * @param date 输入日期
   * @returns 星期几(0 表示周日,1 表示周一,依此类推)
   */
  static getWeekDay(date: number | string | Date): number {
    return DateUtil.getFormatDate(date).getDay();
  }

  /**
   * 获取给定年份和月份的最后一天是几号
   * @param year 年份
   * @param month 月份(1-12)
   * @returns 最后一天的日期
   */
  static getLastDayOfMonth(year: number, month: number): number {
    return new Date(year, month, 0).getDate();
  }

  /**
   * 格式化时间日期字符串
   * @param date 时间日期对象
   * @param options 时间日期格式化选项
   * @param locale 区域设置信息,默认 \"zh-CN\"
   * @returns 格式化后的字符串
   */
  static getFormatTime(
    date: Date,
    options: intl.DateTimeOptions = { dateStyle: \"short\", timeStyle: \"short\", hourCycle: \"h24\" },
    locale: string = \"zh-CN\"
  ): string {
    return new intl.DateTimeFormat(locale, options).format(date);
  }

  /**
   * 格式化时间日期段字符串
   * @param startDate 开始时间日期对象
   * @param endDate 结束时间日期对象
   * @param options 时间日期格式化选项
   * @param locale 区域设置信息,默认 \"zh-CN\"
   * @returns 格式化后的字符串
   */
  static getFormatRange(
    startDate: Date,
    endDate: Date,
    options: intl.DateTimeOptions = { dateStyle: \"short\", timeStyle: \"short\", hourCycle: \"h24\" },
    locale: string = \"zh-CN\"
  ): string {
    return new intl.DateTimeFormat(locale, options).formatRange(startDate, endDate);
  }

  /**
   * 格式化相对时间
   * @param value 相对时间数值
   * @param unit 相对时间单位(\"year\", \"month\", \"day\", 等)
   * @param options 格式化选项
   * @param locale 区域设置信息,默认 \"zh-CN\"
   * @returns 格式化后的字符串
   */
  static getFormatRelativeTime(
    value: number,
    unit: string,
    options?: intl.RelativeTimeFormatInputOptions,
    locale: string = \"zh-CN\"
  ): string {
    return new intl.RelativeTimeFormat(locale, options).format(value, unit as any);
  }

  /**
   * 格式化时间戳,获取提示性时间字符串
   * @param date 时间戳或日期对象
   * @returns 提示性时间字符串
   */
  static getTipDateStr(date: number | string | Date): string {
    const now = Date.now();
    const timeMs = DateUtil.getFormatDate(date).getTime();

    const diff = now - timeMs;

    if (diff < 60 * 1000) {
      return \"刚刚\";
    } else if (diff < 60 * 60 * 1000) {
      return `${Math.floor(diff / (60 * 1000))}分钟前`;
    } else if (diff < 24 * 60 * 60 * 1000) {
      return `${Math.floor(diff / (60 * 60 * 1000))}小时前`;
    } else if (diff < 360 * 24 * 60 * 60 * 1000) {
      return DateUtil.getFormatDateStr(new Date(timeMs), \"MM月dd日\");
    } else {
      return DateUtil.getFormatDateStr(new Date(timeMs), \"yyyy-MM-dd\");
    }
  }

  /**
   * 补零操作
   * @param num 数字
   * @returns 补零后的字符串
   */
  private static padZero(num: number): string {
    return num.toString().padStart(2, \"0\");
  }

  /**
   * 格式化字符串时间戳
   * @param value 字符串时间戳
   * @returns 格式化后的时间戳或原始值
   */
  private static parseTimestamp(value: string): number | string {
    try {
      const parsedValue = parseFloat(value);
      if (isNaN(parsedValue)) return value;

      // 如果是 10 位时间戳,转换为 13 位
      return parsedValue.toString().length === 10 ? parsedValue * 1000 : parsedValue;
    } catch {
      return value;
    }
  }
}
 

import { i18n, intl } from \'@kit.LocalizationKit\';import { NumberUtil } from \'./NumberUtil\';export const DATE_FORMAT1: string = \"yyyy-MM-dd HH:mm:ss\"; // 2025-01-05 14:06:55export const DATE_FORMAT4: string = \"yyyy-MM-dd\"; // 2025-01-05/** * 日期工具类 * * 提供一组静态方法,用于处理和操作日期类型的数据。 * 包括日期格式化、解析、转换等功能。 * * @author CSDN-鸿蒙布道师 * @since 2025/04/03 */export class DateUtil { /** * 获取格式化日期,将传入的日期格式化为 Date 对象。 * * 支持以下输入类型: * - 无参数:返回当前时间的 Date 对象。 * - 字符串:支持多种日期格式(如 \"2025-01-05\" 或 \"2025-01-05 14:06:55\")。 * - 时间戳:支持 10 位或 13 位时间戳。 * - Date 对象:直接返回。 * * @param date 输入的日期参数(可选) * @returns 格式化后的 Date 对象 */ static getFormatDate(date?: number | string | Date): Date { if (!date) { // 如果未提供参数或参数为空,则返回当前时间 return new Date(); } if (typeof date === \"string\") { // 处理字符串日期 if (date.trim().length === 0) { return new Date(); // 空字符串返回当前时间 } // 尝试解析时间戳 const timestamp = NumberUtil.toInt(date); if (timestamp > 0) { return new Date(timestamp * (date.length === 10 ? 1000 : 1)); // 转换为毫秒级时间戳 } // 标准化日期字符串格式 let normalizedDate = date .replace(/[-年月日]/g, \'/\') // 替换分隔符 .replace(/[:时分秒]/g, \':\') // 替换时间分隔符 .replace(/\\s+/g, \' \') // 去除多余空格 .trim(); // 补齐时间部分(如 \"2025-01-05 14\" -> \"2025-01-05 14:00:00\") if (normalizedDate.split(\' \').length === 2 && !normalizedDate.includes(\':\')) { normalizedDate += \':00:00\'; } try { return new Date(normalizedDate); // 尝试解析标准化后的日期字符串 } catch { throw new Error(`Invalid date string: ${date}`); } } if (typeof date === \"number\") { // 处理时间戳 const timestamp = date * (date.toString().length === 10 ? 1000 : 1); // 转换为毫秒级时间戳 return new Date(timestamp); } // 如果是 Date 对象,直接返回 return new Date(date); } /** * 获取格式化日期,将传入的日期格式化为指定格式的字符串 * * 支持自定义格式化模板,例如: * - \"yyyy-MM-dd HH:mm:ss\" -> \"2025-01-05 14:06:55\" * - \"yyyy/MM/dd HH:mm\" -> \"2025/01/05 14:06\" * - \"HH:mm:ss.fff\" -> \"14:06:55.123\" * * @param date 输入的日期参数(支持时间戳、字符串或 Date 对象) * @param format 格式化字符串,默认为 \"yyyy-MM-dd HH:mm:ss\" * @returns 格式化后的日期字符串 */ static getFormatDateStr(date: number | string | Date, format: string = DATE_FORMAT1): string { // 将输入日期标准化为 Date 对象 const normalizedDate = DateUtil.getFormatDate(date); // 定义格式化占位符及其对应的值 const formatMap = { yyyy: normalizedDate.getFullYear().toString(), // 年份 MM: DateUtil.padZero(normalizedDate.getMonth() + 1), // 月份 (0-11) dd: DateUtil.padZero(normalizedDate.getDate()), // 日期 (1-31) HH: DateUtil.padZero(normalizedDate.getHours()), // 小时 (0-23) mm: DateUtil.padZero(normalizedDate.getMinutes()), // 分钟 (0-59) ss: DateUtil.padZero(normalizedDate.getSeconds()), // 秒数 (0-59) fff: normalizedDate.getMilliseconds().toString().padStart(3, \'0\'), // 毫秒 (0-999) }; // 替换格式化字符串中的占位符 return Object.keys(formatMap).reduce((formatted, placeholder) => { const value = (formatMap as Record)[placeholder]; return formatted.replace(new RegExp(placeholder, \'g\'), value); }, format); } /** * 获取今天的日期 * @returns 当前日期的 Date 对象 */ static getToday(): Date { return new Date(); } /** * 获取今天的时间戳 * @returns 当前时间的时间戳(毫秒) */ static getTodayTime(): number { return Date.now(); // 使用 Date.now() 替代 new Date().getTime(),性能更高 } /** * 获取今天的时间,字符串类型 * @param format 格式化字符串,默认为 \"yyyy-MM-dd HH:mm:ss\" * @returns 格式化后的日期字符串 */ static getTodayStr(format: string = DATE_FORMAT1): string { return DateUtil.getFormatDateStr(new Date(), format); } /** * 判断日期是否是今天 * @param date 输入日期(支持时间戳、字符串或 Date 对象) * @returns 如果是今天,则返回 true;否则返回 false */ static isToday(date: number | string | Date): boolean { const today = DateUtil.getTodayStr(DATE_FORMAT4); // yyyy-MM-dd const inputDate = DateUtil.getFormatDateStr(date, DATE_FORMAT4); return today === inputDate; } /** * 获取当前年份 * @returns 当前年份 */ static getNowYear(): number { return new Date().getFullYear(); } /** * 获取当前月份(1-12) * @returns 当前月份 */ static getNowMonth(): number { return new Date().getMonth() + 1; // 月份从 0 开始,需要加 1 } /** * 获取当前日 * @returns 当前日期 */ static getNowDay(): number { return new Date().getDate(); } /** * 判断是否是闰年 * @param year 不传时默认为当前年 * @returns 如果是闰年,则返回 true;否则返回 false */ static isLeapYear(year: number | Date = new Date()): boolean { year = year instanceof Date ? year.getFullYear() : year; return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; } /** * 获取指定年份的天数 * @param year 指定年份 * @returns 该年份的天数(365 或 366) */ static getDaysByYear(year: number): number { return DateUtil.isLeapYear(year) ? 366 : 365; } /** * 获取指定月份的天数 * @param year 指定年份 * @param month 指定月份(1-12) * @returns 该月份的天数 */ static getDaysByMonth(year: number, month: number): number { if (month === 2) { return DateUtil.isLeapYear(year) ? 29 : 28; } return [4, 6, 9, 11].includes(month) ? 30 : 31; } /** * 判断两个日期是否是同一年 * @param date1 第一个日期 * @param date2 第二个日期 * @returns 如果是同一年,则返回 true;否则返回 false */ static isSameYear(date1: number | string | Date, date2: number | string | Date): boolean { const d1 = DateUtil.getFormatDate(date1); const d2 = DateUtil.getFormatDate(date2); return d1.getFullYear() === d2.getFullYear(); } /** * 判断两个日期是否是同一月 * @param date1 第一个日期 * @param date2 第二个日期 * @returns 如果是同一月,则返回 true;否则返回 false */ static isSameMonth(date1: number | string | Date, date2: number | string | Date): boolean { const d1 = DateUtil.getFormatDate(date1); const d2 = DateUtil.getFormatDate(date2); return d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth(); } /** * 判断两个日期是否是同一周 * @param date1 第一个日期 * @param date2 第二个日期 * @returns 如果是同一周,则返回 true;否则返回 false */ static isSameWeek(date1: number | string | Date, date2: number | string | Date): boolean { const oneDayTime = 1000 * 60 * 60 * 24; // 一天的毫秒数 const dayCount1 = Math.floor(DateUtil.getFormatDate(date1).getTime() / oneDayTime); const dayCount2 = Math.floor(DateUtil.getFormatDate(date2).getTime() / oneDayTime); const weekIndex1 = Math.floor((dayCount1 + 4) / 7); const weekIndex2 = Math.floor((dayCount2 + 4) / 7); return weekIndex1 === weekIndex2; } /** * 判断两个日期是否是同一天 * @param date1 第一个日期 * @param date2 第二个日期 * @returns 如果是同一天,则返回 true;否则返回 false */ static isSameDay(date1: number | string | Date, date2: number | string | Date): boolean { const d1 = DateUtil.getFormatDate(date1); const d2 = DateUtil.getFormatDate(date2); return ( d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() && d1.getDate() === d2.getDate() ); } /** * 获取日历对象,并设置日历对象内部的时间日期 * @param date 输入日期(支持时间戳、字符串或 Date 对象) * @param type 合法的日历类型,默认为区域默认的日历类型 * @param locale 合法的语言环境值,默认为 \"zh-Hans\" * @returns 日历对象 */ static getCalendar( date?: number | string | Date, type: string = \"gregory\", locale: string = \"zh-Hans\" ): i18n.Calendar { const normalizedDate = DateUtil.getFormatDate(date); const calendar = i18n.getCalendar(locale, type); calendar.setTime(normalizedDate); return calendar; } /** * 获取日历对象中与 field 相关联的值 * @param field 指定字段 * @param date 输入日期(支持时间戳、字符串或 Date 对象) * @param type 合法的日历类型,默认为区域默认的日历类型 * @param locale 合法的语言环境值,默认为 \"zh-Hans\" * @returns 字段的值 */ static getCalendarField( field: string, date?: number | string | Date, type: string = \"gregory\", locale: string = \"zh-Hans\" ): number { const normalizedDate = DateUtil.getFormatDate(date); const calendar = i18n.getCalendar(locale, type); calendar.setTime(normalizedDate); return calendar.get(field); } /** * 在日历的给定字段进行加减操作 * @param date 输入日期(支持时间戳、字符串或 Date 对象) * @param field 指定字段 * @param amount 加减值 * @param type 合法的日历类型,默认为区域默认的日历类型 * @param locale 合法的语言环境值,默认为 \"zh-Hans\" * @returns 修改后的日期 */ static getCalendarAdd( date: number | string | Date, field: string, amount: number, type: string = \"gregory\", locale: string = \"zh-Hans\" ): Date { const normalizedDate = DateUtil.getFormatDate(date); const calendar = i18n.getCalendar(locale, type); calendar.setTime(normalizedDate); calendar.add(field, amount); return new Date(calendar.getTimeInMillis()); } /** * 判断指定的日期在日历中是否为周末 * @param date 输入日期(支持时间戳、字符串或 Date 对象) * @returns 如果是周末,则返回 true;否则返回 false */ static isWeekend(date?: number | string | Date): boolean { const normalizedDate = DateUtil.getFormatDate(date); const calendar = i18n.getCalendar(\"zh-Hans\"); calendar.setTime(normalizedDate); return calendar.isWeekend(normalizedDate); } /** * 比较日历和指定日期相差的天数(按毫秒级的精度,不足一天将按一天进行计算)。 * 正数代表日历时间更早,负数代表日历时间更晚。 * @param date1 第一个日期 * @param date2 第二个日期 * @returns 相差的天数 */ static compareDays(date1: number | string | Date, date2: number | string | Date): number { const d1 = DateUtil.getFormatDate(date1).getTime(); const d2 = DateUtil.getFormatDate(date2).getTime(); const diffMs = d2 - d1; // 时间差(毫秒) return Math.ceil(diffMs / (1000 * 60 * 60 * 24)); // 转换为天数,向上取整 } /** * 比较两个日期相差的毫秒数 * @param date1 第一个日期 * @param date2 第二个日期 * @param floor 是否向下取整,默认 false * @returns 相差的毫秒数 */ static compareDate(date1: number | string | Date, date2: number | string | Date, floor: boolean = false): number { const diff = DateUtil.getFormatDate(date2).getTime() - DateUtil.getFormatDate(date1).getTime(); return floor ? Math.floor(diff) : diff; } /** * 获取前几天或后几天的日期 * @param date 输入日期 * @param amount 偏移天数(正数表示后几天,负数表示前几天) * @returns 新的日期对象 */ static getAmountDay(date: number | string | Date, amount: number): Date { return DateUtil.getCalendarAdd(date, \"date\", amount); } /** * 获取前几天或后几天的日期,返回字符串 * @param date 输入日期 * @param amount 偏移天数(正数表示后几天,负数表示前几天) * @param format 格式化字符串,默认 \"yyyy-MM-dd\" * @returns 格式化后的日期字符串 */ static getAmountDayStr(date: number | string | Date, amount: number, format: string = DATE_FORMAT4): string { return DateUtil.getFormatDateStr(DateUtil.getAmountDay(date, amount), format); } /** * 获取前一天的日期 * @param date 输入日期 * @returns 新的日期对象 */ static getBeforeDay(date: number | string | Date): Date { return DateUtil.getAmountDay(date, -1); } /** * 获取前一天的日期,返回字符串 * @param date 输入日期 * @param format 格式化字符串,默认 \"yyyy-MM-dd\" * @returns 格式化后的日期字符串 */ static getBeforeDayStr(date: number | string | Date, format: string = DATE_FORMAT4): string { return DateUtil.getAmountDayStr(date, -1, format); } /** * 获取后一天的日期 * @param date 输入日期 * @returns 新的日期对象 */ static getAfterDay(date: number | string | Date): Date { return DateUtil.getAmountDay(date, 1); } /** * 获取后一天的日期,返回字符串 * @param date 输入日期 * @param format 格式化字符串,默认 \"yyyy-MM-dd\" * @returns 格式化后的日期字符串 */ static getAfterDayStr(date: number | string | Date, format: string = DATE_FORMAT4): string { return DateUtil.getAmountDayStr(date, 1, format); } /** * 获取给定日期是当月的第几周 * @param date 输入日期 * @returns 当月的第几周 */ static getWeekOfMonth(date: number | string | Date): number { return DateUtil.getCalendarField(\"week_of_month\", date); } /** * 获取给定日期是星期几 * @param date 输入日期 * @returns 星期几(0 表示周日,1 表示周一,依此类推) */ static getWeekDay(date: number | string | Date): number { return DateUtil.getFormatDate(date).getDay(); } /** * 获取给定年份和月份的最后一天是几号 * @param year 年份 * @param month 月份(1-12) * @returns 最后一天的日期 */ static getLastDayOfMonth(year: number, month: number): number { return new Date(year, month, 0).getDate(); } /** * 格式化时间日期字符串 * @param date 时间日期对象 * @param options 时间日期格式化选项 * @param locale 区域设置信息,默认 \"zh-CN\" * @returns 格式化后的字符串 */ static getFormatTime( date: Date, options: intl.DateTimeOptions = { dateStyle: \"short\", timeStyle: \"short\", hourCycle: \"h24\" }, locale: string = \"zh-CN\" ): string { return new intl.DateTimeFormat(locale, options).format(date); } /** * 格式化时间日期段字符串 * @param startDate 开始时间日期对象 * @param endDate 结束时间日期对象 * @param options 时间日期格式化选项 * @param locale 区域设置信息,默认 \"zh-CN\" * @returns 格式化后的字符串 */ static getFormatRange( startDate: Date, endDate: Date, options: intl.DateTimeOptions = { dateStyle: \"short\", timeStyle: \"short\", hourCycle: \"h24\" }, locale: string = \"zh-CN\" ): string { return new intl.DateTimeFormat(locale, options).formatRange(startDate, endDate); } /** * 格式化相对时间 * @param value 相对时间数值 * @param unit 相对时间单位(\"year\", \"month\", \"day\", 等) * @param options 格式化选项 * @param locale 区域设置信息,默认 \"zh-CN\" * @returns 格式化后的字符串 */ static getFormatRelativeTime( value: number, unit: string, options?: intl.RelativeTimeFormatInputOptions, locale: string = \"zh-CN\" ): string { return new intl.RelativeTimeFormat(locale, options).format(value, unit as any); } /** * 格式化时间戳,获取提示性时间字符串 * @param date 时间戳或日期对象 * @returns 提示性时间字符串 */ static getTipDateStr(date: number | string | Date): string { const now = Date.now(); const timeMs = DateUtil.getFormatDate(date).getTime(); const diff = now - timeMs; if (diff < 60 * 1000) { return \"刚刚\"; } else if (diff < 60 * 60 * 1000) { return `${Math.floor(diff / (60 * 1000))}分钟前`; } else if (diff < 24 * 60 * 60 * 1000) { return `${Math.floor(diff / (60 * 60 * 1000))}小时前`; } else if (diff < 360 * 24 * 60 * 60 * 1000) { return DateUtil.getFormatDateStr(new Date(timeMs), \"MM月dd日\"); } else { return DateUtil.getFormatDateStr(new Date(timeMs), \"yyyy-MM-dd\"); } } /** * 补零操作 * @param num 数字 * @returns 补零后的字符串 */ private static padZero(num: number): string { return num.toString().padStart(2, \"0\"); } /** * 格式化字符串时间戳 * @param value 字符串时间戳 * @returns 格式化后的时间戳或原始值 */ private static parseTimestamp(value: string): number | string { try { const parsedValue = parseFloat(value); if (isNaN(parsedValue)) return value; // 如果是 10 位时间戳,转换为 13 位 return parsedValue.toString().length === 10 ? parsedValue * 1000 : parsedValue; } catch { return value; } }}