消消方块阵换皮表情
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

107 lines
4.0 KiB

import { _decorator } from 'cc';
import { Singleton } from '../../tools/Singleton';
const { ccclass } = _decorator;
const MS_PER_MINUTE = 60 * 1000;
const MS_PER_DAY = 24 * 60 * MS_PER_MINUTE;
@ccclass('TimeModule')
export class TimeModule extends Singleton {
/** ISO 或已解析的 UTC 毫秒;热路径传 `number` 可避免 `new Date` 与字符串解析 */
private static utcMs(t: string | number): number {
return typeof t === 'number' ? t : new Date(t).getTime();
}
/** 当前 UTC 时间毫秒数(无 Date 分配,适合每帧调用) */
get now(): number {
return Date.now();
}
/**
* 将本地日历时刻按「数值等同 UTC」方式表示的毫秒数(常用于与服务器约定字段对齐)
* 等价:UTC 时间与本地墙钟相同数字时的 epoch 毫秒
*/
get localNow(): number {
const d = new Date();
return d.getTime() + d.getTimezoneOffset() * MS_PER_MINUTE;
}
/** 解析带时区的时间字符串为 UTC 毫秒,如 2026-02-08T00:00:00+08:00 */
getUTCTimeByLocalTimeStr(timeStr: string): number {
return new Date(timeStr).getTime();
}
/** 带时区字符串 → 本地墙钟对齐的「伪 UTC」毫秒(与 localNow 同一套坐标系) */
getLocalTimeByLocalTimeStr(timeStr: string): number {
const d = new Date(timeStr);
return d.getTime() + d.getTimezoneOffset() * MS_PER_MINUTE;
}
/** 本地墙钟对齐毫秒 → 真实 UTC 毫秒 */
getUTCTimeByLocalTime(localTime: number): number {
const d = new Date(localTime);
return d.getTime() - d.getTimezoneOffset() * MS_PER_MINUTE;
}
/**
* 根据时间段判断当前时间状态(比较均在真实 UTC 时间轴上)
* @param timeNow 当前 UTC 毫秒
* @param startTime 活动开始:ISO 字符串(含时区)或已解析的 UTC 毫秒
* @param endTime 活动结束:同上
* @param name 可选;非空会打日志,勿在高频逻辑中传入
*/
checkTimeStatus(timeNow: number, startTime: string | number, endTime: string | number, name = ''): 0 | 1 | 2 {
const start = TimeModule.utcMs(startTime);
const end = TimeModule.utcMs(endTime);
if (name) {
console.log('活动时间:', name, timeNow, start, end);
}
if (timeNow > end) return 2;
if (timeNow >= start) return 1;
return 0;
}
/**
* 当天剩余毫秒数(到下一次「本地/UTC」的 0 点)
* 仅分配 **一个** `Date`(原实现为两个)
*/
getRemainTimeForCurrentDay(timeNow: number | null = null, isLocal = true): number {
const d = new Date(timeNow ?? Date.now());
const now = d.getTime();
if (isLocal) {
d.setHours(24, 0, 0, 0);
} else {
d.setUTCHours(24, 0, 0, 0);
}
return d.getTime() - now;
}
/**
* 距离活动结束的剩余毫秒,负表示已过期
* @param endTime 结束时刻:ISO 字符串(含时区)或 UTC 毫秒
* @param timeNow 当前 UTC 毫秒,默认 `Date.now()`
*/
getRemainTime(endTime: string | number, timeNow: number = Date.now()): number {
return TimeModule.utcMs(endTime) - timeNow;
}
/** 自 startTime 起算的第几天(满 24h 计一天,向下取整);`startTime` 为 number 时零分配 */
getDayAfterStartTime(timeNow: number, startTime: number | string): number {
const start = typeof startTime === 'string' ? new Date(startTime).getTime() : startTime;
return Math.floor((timeNow - start) / MS_PER_DAY);
}
/** 与当前真实时间是否同一自然日(本地时区);仅 **一个** `Date` 实例 */
isSameDay(lastLoginTime: number): boolean {
const d = new Date(lastLoginTime);
const y = d.getFullYear();
const m = d.getMonth();
const day = d.getDate();
d.setTime(Date.now());
return d.getFullYear() === y && d.getMonth() === m && d.getDate() === day;
}
}