fix(server): 业务日期'今天'统一为中国日期,避免凌晨 UTC 偏一天

joinDate/leaveDate/checkInDate/sync 起始日等业务日期默认值原来用
dayjs().utc()(UTC 今天),在国内 00:00-07:59 会取到昨天。
统一改为 dayjs().utcOffset(8)(固定 UTC+8 中国日期),与考勤周边界
修复保持一致;pending-tasks/controller-base 的本地 dayjs() 也显式化。
This commit is contained in:
2026-08-08 17:58:16 +08:00
parent 782b43ef0a
commit 7905f1ee23
8 changed files with 11 additions and 11 deletions

View File

@@ -56,11 +56,11 @@ function teacherScopedCountSql(sql: (scope: StudentAccessScope) => string): SqlB
}
function today(): string {
return dayjs().format('YYYY-MM-DD');
return dayjs().utcOffset(8).format('YYYY-MM-DD');
}
function inDays(days: number): string {
return dayjs().add(days, 'day').format('YYYY-MM-DD');
return dayjs().utcOffset(8).add(days, 'day').format('YYYY-MM-DD');
}
const TASKS: readonly TaskDefinition[] = [

View File

@@ -250,7 +250,7 @@ async function importCheckins(
continue;
}
const checkInDate = toDateString(row.checkInDate) ?? dayjs().utc().format('YYYY-MM-DD');
const checkInDate = toDateString(row.checkInDate) ?? dayjs().utcOffset(8).format('YYYY-MM-DD');
const billingStartDate = toDateString(row.billingStartDate) ?? checkInDate;
const checkOutDate = toDateString(row.checkOutDate);
const isHistoricalRecord = Boolean(checkOutDate);

View File

@@ -33,7 +33,7 @@ export abstract class AttendanceControllerBase {
) {}
protected getTodayDateOnly(): string {
return dayjs().format('YYYY-MM-DD');
return dayjs().utcOffset(8).format('YYYY-MM-DD');
}
protected canManageAllAttendance(req: { user: RequestUser }): boolean {

View File

@@ -81,7 +81,7 @@ export class ClassesQueriesService {
const existingByStudentId = new Map(
existingClassStudents.map((classStudent) => [classStudent.studentId, classStudent]),
);
const today = dayjs().utc().format('YYYY-MM-DD');
const today = dayjs().utcOffset(8).format('YYYY-MM-DD');
let skipped = 0;
const memberships = studentIds.flatMap((studentId) => {
const existing = existingByStudentId.get(studentId);

View File

@@ -185,7 +185,7 @@ export class ClassesService {
this.classStudentRepo.create({
classId: saved.id,
studentId: sid,
joinDate: dayjs().utc().format('YYYY-MM-DD'),
joinDate: dayjs().utcOffset(8).format('YYYY-MM-DD'),
}),
);
await this.classStudentRepo.save(entries);
@@ -306,7 +306,7 @@ export class ClassesService {
const existingByStudentId = new Map(
existing.map((classStudent) => [classStudent.studentId, classStudent]),
);
const today = dayjs().utc().format('YYYY-MM-DD');
const today = dayjs().utcOffset(8).format('YYYY-MM-DD');
let skipped = 0;
const memberships = uniqueStudentIds.flatMap((studentId) => {
const current = existingByStudentId.get(studentId);
@@ -342,7 +342,7 @@ export class ClassesService {
if (membership.status !== 'active') throw new BadRequestException('学生已离班');
membership.status = 'left';
membership.leaveDate = dayjs().utc().format('YYYY-MM-DD');
membership.leaveDate = dayjs().utcOffset(8).format('YYYY-MM-DD');
await this.classStudentRepo.save(membership);
return { success: true };
}

View File

@@ -133,7 +133,7 @@ export class OccupancyImportService {
);
}
const checkInDate = row.checkInDate?.trim() || dayjs().utc().format('YYYY-MM-DD');
const checkInDate = row.checkInDate?.trim() || dayjs().utcOffset(8).format('YYYY-MM-DD');
const checkOutDate = row.checkOutDate?.trim();
const billingStartDate = row.billingStartDate?.trim() || checkInDate;
const isHistoricalRecord = Boolean(checkOutDate);

View File

@@ -46,7 +46,7 @@ export class ScheduleSyncService {
opUserId = 'manager',
attendanceMachineOnly = false,
): Promise<ScheduleSyncResult> {
const startDate = dateFrom || dayjs().utc().format('YYYY-MM-DD');
const startDate = dateFrom || dayjs().utcOffset(8).format('YYYY-MM-DD');
const normalizedDays = Number.isFinite(days) ? Math.max(1, Math.floor(days)) : 30;
const endDate = addDays(startDate, normalizedDays - 1);

View File

@@ -305,7 +305,7 @@ export class SyncService {
}
async getScheduleSyncStatus(date?: string) {
return this.scheduleSyncService.getStatus(date || dayjs().utc().format('YYYY-MM-DD'));
return this.scheduleSyncService.getStatus(date || dayjs().utcOffset(8).format('YYYY-MM-DD'));
}
/**