Files
mini-programs/src/utils/timeUtils.ts
张成 0090fc45c6 1
2025-11-09 18:05:03 +08:00

345 lines
9.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import dayjs from "dayjs";
/**
* 安全地将字符串转换为 Date 对象,兼容 iOS
* iOS 不支持 "yyyy-MM-dd HH:mm:ss" 格式,需要转换为 "yyyy-MM-ddTHH:mm:ss" 或 "yyyy/MM/dd HH:mm:ss"
* @param dateStr 日期字符串
* @returns Date 对象
*/
const parseDate = (dateStr: string): Date => {
if (!dateStr) return new Date();
// 将 "yyyy-MM-dd HH:mm:ss" 格式转换为 "yyyy-MM-ddTHH:mm:ss" (ISO 8601)
// 替换第一个空格为 T
const isoStr = dateStr.replace(/^(\d{4}-\d{2}-\d{2})\s(\d{2}:\d{2}(?::\d{2})?)$/, '$1T$2');
return new Date(isoStr);
};
/**
* 获取下一个整点时间
* @returns 格式为 YYYY-MM-DD HH:mm 的字符串
*/
export const getNextHourTime = (): string => {
const now = dayjs();
const nextHour = now.add(1, "hour").startOf("hour");
return nextHour.format("YYYY-MM-DD HH:mm");
};
/**
* 根据开始时间计算结束时间2小时后
* @param startTime 开始时间,格式为 YYYY-MM-DD HH:mm
* @returns 格式为 YYYY-MM-DD HH:mm 的字符串
*/
export const getEndTime = (startTime: string): string => {
const startDateTime = dayjs(startTime);
const endDateTime = startDateTime.add(2, "hour");
return endDateTime.format("YYYY-MM-DD HH:mm");
};
export const getDateStr = (date: Date): string => {
return dayjs(date).format("YYYY-MM-DD HH:mm");
};
export const getDate = (date: string): string => {
return dayjs(date).format("YYYY年MM月DD日");
};
export const getDay = (date?: string | Date): string => {
if (!date) {
return dayjs().format("YYYY-MM-DD");
}
return dayjs(date).format("YYYY-MM-DD");
};
export const getMonth = (date?: string | Date): string => {
if (!date) {
return dayjs().format("MM月 YYYY");
}
return dayjs(date).format("MM月 YYYY");
};
export const getWeekend = (date?: string | Date): [Date, Date] => {
const today = dayjs(date);
const currentDayOfWeek = today.day();
console.log("currentDayOfWeek", currentDayOfWeek);
const saturdayOffset = 6 - currentDayOfWeek;
const sundayOffset = 7 - currentDayOfWeek;
const sat = today.add(saturdayOffset, "day");
const sun = today.add(sundayOffset, "day");
return [sat.toDate(), sun.toDate()];
};
export const getWeekendOfCurrentWeek = (days = 7): Date[] => {
const dayList: Date[] = [];
for (let i = 0; i < days; i++) {
const day = dayjs().add(i, "day").toDate();
dayList.push(day);
}
return dayList;
};
export const getTime = (time: string): string => {
const timeObj = dayjs(time);
const hour = timeObj.hour();
const minute = timeObj.minute();
// 判断是上午还是下午
const period = hour <= 12 ? "AM" : "PM";
// 转换为12小时制
const hour12 = hour === 0 ? 0 : hour > 12 ? hour - 12 : hour;
// 格式化分钟,保证两位数
const minuteStr = minute.toString().padStart(2, "0");
return `${hour12}:${minuteStr} ${period}`;
};
/**
* 格式化时间显示(相对时间)
* @param timeStr 时间字符串
* @returns 格式化后的时间字符串
*/
export const formatRelativeTime = (timeStr: string): string => {
if (!timeStr) return "";
const date = parseDate(timeStr);
const now = new Date();
// 获取日期部分(年-月-日),忽略时间
const getDateString = (d: Date) => {
const year = d.getFullYear();
const month = d.getMonth() + 1;
const day = d.getDate();
return `${year}-${month.toString().padStart(2, "0")}-${day
.toString()
.padStart(2, "0")}`;
};
const dateStr = getDateString(date);
const nowStr = getDateString(now);
// 计算日期差
const dateObj = new Date(dateStr);
const nowObj = new Date(nowStr);
const diffTime = nowObj.getTime() - dateObj.getTime();
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
if (diffDays === 0) {
// 今天
const hours = date.getHours();
const minutes = date.getMinutes();
return `今天 ${hours.toString().padStart(2, "0")}:${minutes
.toString()
.padStart(2, "0")}`;
} else if (diffDays === 1) {
// 昨天
const hours = date.getHours();
const minutes = date.getMinutes();
return `昨天 ${hours.toString().padStart(2, "0")}:${minutes
.toString()
.padStart(2, "0")}`;
} else if (diffDays < 7) {
// 一周内显示天数
return `${diffDays}天前`;
} else {
// 超过一周显示完整日期
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const hours = date.getHours();
const minutes = date.getMinutes();
return `${year}-${month.toString().padStart(2, "0")}-${day
.toString()
.padStart(2, "0")} ${hours.toString().padStart(2, "0")}:${minutes
.toString()
.padStart(2, "0")}`;
}
};
/**
* 格式化时间显示(简短相对时间)
* @param timeStr 时间字符串
* @returns 格式化后的时间字符串
*/
export const formatShortRelativeTime = (timeStr: string): string => {
if (!timeStr) return "";
const date = parseDate(timeStr);
const now = new Date();
// 获取日期部分(年-月-日),忽略时间
const getDateString = (d: Date) => {
const year = d.getFullYear();
const month = d.getMonth() + 1;
const day = d.getDate();
return `${year}-${month.toString().padStart(2, "0")}-${day
.toString()
.padStart(2, "0")}`;
};
const dateStr = getDateString(date);
const nowStr = getDateString(now);
// 计算日期差
const dateObj = new Date(dateStr);
const nowObj = new Date(nowStr);
const diffTime = nowObj.getTime() - dateObj.getTime();
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
// 如果是今天,显示具体时间
if (diffDays === 0) {
const diff = now.getTime() - date.getTime();
const minutes = Math.floor(diff / (1000 * 60));
const hours = Math.floor(diff / (1000 * 60 * 60));
if (minutes < 1) {
return "刚刚";
} else if (minutes < 60) {
return `${minutes}分钟前`;
} else {
return `${hours}小时前`;
}
} else if (diffDays === 1) {
return "1天前";
} else if (diffDays < 7) {
return `${diffDays}天前`;
} else {
const month = date.getMonth() + 1;
const day = date.getDate();
return `${month}${day}`;
}
};
/**
* 格式化球局时间显示(例如:明天(周五)下午5点
* @param timeStr 时间字符串
* @returns 格式化后的时间字符串
*/
export const formatGameTime = (timeStr: string): string => {
if (!timeStr) return "";
const date = parseDate(timeStr);
const now = new Date();
// 获取星期几
const weekDays = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
const weekDay = weekDays[date.getDay()];
// 获取小时和分钟
const hours = date.getHours();
const minutes = date.getMinutes();
// 判断上午/下午/晚上
let period = "";
let displayHour = hours;
if (hours >= 0 && hours < 6) {
period = "凌晨";
} else if (hours >= 6 && hours < 12) {
period = "上午";
} else if (hours >= 12 && hours < 18) {
period = "下午";
displayHour = hours === 12 ? 12 : hours - 12;
} else {
period = "晚上";
displayHour = hours - 12;
}
// 格式化时间部分
const timeStr2 =
minutes === 0 ? `${displayHour}` : `${displayHour}${minutes}`;
// 获取日期部分(年-月-日),忽略时间
const getDateString = (d: Date) => {
const year = d.getFullYear();
const month = d.getMonth() + 1;
const day = d.getDate();
return `${year}-${month.toString().padStart(2, "0")}-${day
.toString()
.padStart(2, "0")}`;
};
const dateStr = getDateString(date);
const nowStr = getDateString(now);
// 计算日期差
const dateObj = new Date(dateStr);
const nowObj = new Date(nowStr);
const diffTime = dateObj.getTime() - nowObj.getTime();
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
// 根据日期差返回不同格式
if (diffDays === 0) {
// 今天
return `今天(${weekDay})${period}${timeStr2}`;
} else if (diffDays === 1) {
// 明天
return `明天(${weekDay})${period}${timeStr2}`;
} else if (diffDays === 2) {
// 后天
return `后天(${weekDay})${period}${timeStr2}`;
} else if (diffDays > 2 && diffDays <= 7) {
// 一周内
return `${weekDay}${period}${timeStr2}`;
} else {
// 超过一周,显示具体日期
const month = date.getMonth() + 1;
const day = date.getDate();
return `${month}${day}日(${weekDay})${period}${timeStr2}`;
}
};
/**
* 计算时长(结束时间 - 开始时间)
* @param startTime 开始时间字符串
* @param endTime 结束时间字符串
* @returns 格式化后的时长字符串2小时、1.5小时、30分钟
*/
export const calculateDuration = (
startTime: string,
endTime: string
): string => {
if (!startTime || !endTime) return "";
const start = parseDate(startTime);
const end = parseDate(endTime);
// 计算时间差(毫秒)
const diffMs = end.getTime() - start.getTime();
// 转换为分钟
const diffMinutes = Math.floor(diffMs / (1000 * 60));
// 转换为小时
const hours = Math.floor(diffMinutes / 60);
const minutes = diffMinutes % 60;
// 格式化输出
if (hours > 0 && minutes > 0) {
return `${hours}.5小时`;
} else if (hours > 0) {
return `${hours}小时`;
} else if (minutes > 0) {
return `${minutes}分钟`;
} else {
return "";
}
};
export const getOneMonth = (): Date[] => {
const dates: Date[] = [];
const currentDate = dayjs();
const nextMonth = dayjs().add(1, "month");
// 从当前日期开始,遍历到下个月的同一天
let date = currentDate;
while (date.isBefore(nextMonth) || date.isSame(nextMonth, "day")) {
dates.push(date.toDate());
date = date.add(1, "day");
}
return dates;
};