Files
jizhi/frontend/lib/shared/services/shanghai_time.dart
T
2026-07-24 23:11:20 +08:00

89 lines
2.5 KiB
Dart

class ShanghaiTime {
ShanghaiTime._();
static const offset = Duration(hours: 8);
/// A device-timezone-independent civil clock for Asia/Shanghai.
static DateTime get now => toCivil(DateTime.now());
static DateTime toCivil(DateTime instant) {
final shifted = instant.toUtc().add(offset);
return DateTime(
shifted.year,
shifted.month,
shifted.day,
shifted.hour,
shifted.minute,
shifted.second,
shifted.millisecond,
shifted.microsecond,
);
}
static DateTime civilToUtc(DateTime civil) => DateTime.utc(
civil.year,
civil.month,
civil.day,
civil.hour,
civil.minute,
civil.second,
civil.millisecond,
civil.microsecond,
).subtract(offset);
/// Parses API/cache instants. Legacy values without a zone were stored as UTC.
static DateTime parseUtcInstant(String value) {
final parsed = DateTime.parse(value);
if (value.endsWith('Z') || RegExp(r'[+-]\d{2}:?\d{2}$').hasMatch(value)) {
return parsed.toUtc();
}
return DateTime.utc(
parsed.year,
parsed.month,
parsed.day,
parsed.hour,
parsed.minute,
parsed.second,
parsed.millisecond,
parsed.microsecond,
);
}
static DateTime parseCivil(String value) => toCivil(parseUtcInstant(value));
static DateTime startOfDayUtc(DateTime civil) =>
civilToUtc(DateTime(civil.year, civil.month, civil.day));
static ({DateTime start, DateTime end}) monthRangeUtc(int year, int month) =>
(
start: civilToUtc(DateTime(year, month, 1)),
end: civilToUtc(DateTime(year, month + 1, 1)),
);
static ({DateTime start, DateTime end}) yearRangeUtc(int year) => (
start: civilToUtc(DateTime(year, 1, 1)),
end: civilToUtc(DateTime(year + 1, 1, 1)),
);
static ({DateTime start, DateTime end}) weekRangeUtc(DateTime civil) {
final date = DateTime(civil.year, civil.month, civil.day);
final start = date.subtract(Duration(days: date.weekday - DateTime.monday));
return (
start: civilToUtc(start),
end: civilToUtc(start.add(const Duration(days: 7))),
);
}
static String formatCivil(DateTime value) =>
'${value.year.toString().padLeft(4, '0')}-'
'${value.month.toString().padLeft(2, '0')}-'
'${value.day.toString().padLeft(2, '0')} '
'${value.hour.toString().padLeft(2, '0')}:'
'${value.minute.toString().padLeft(2, '0')}';
static String formatDateTime(DateTime instant) {
final value = toCivil(instant);
return formatCivil(value);
}
}