HarmonyOS鸿蒙Next中类似于swiftDate的日期时间操作库
HarmonyOS鸿蒙Next中类似于swiftDate的日期时间操作库 之前在iOS开发中,有一款三方库 swiftDate,挺好用,如何实现一个类似的库
SwiftDate 可以自动识别所有主流的日期时间格式(ISO8601、RSS、Alt RSS、.NET、SQL、HTTP 等),您也可以提供自定义格式
// All default datetime formats (15+) are recognized automatically
let _ = "2010-05-20 15:30:00".toDate()
// You can also provide your own format!
let _ = "2010-05-20 15:30".toDate("yyyy-MM-dd HH:mm")
// All ISO8601 variants are supported too with timezone parsing!
let _ = "2017-09-17T11:59:29+02:00".toISODate()
// RSS, Extended, HTTP, SQL, .NET and all the major variants are supported!
let _ = "19 Nov 2015 22:20:40 +0100".toRSS(alt: true)
按照SwiftDate 进行一些常用日期时间工具类实现
/**
* 日期时间工具类
* 类似 SwiftDate 的功能实现
*/
export interface DateComponents {
year: number;
month: number;
day: number;
hour: number;
minute: number;
second: number;
millisecond: number;
weekday?: number; // 1-7, 1=Sunday
}
export interface DateRange {
start: Date;
end: Date;
}
export class DateUtils {
/**
* 日期格式化
* [@param](/user/param) date 日期对象
* [@param](/user/param) format 格式化字符串
* [@returns](/user/returns) 格式化后的字符串
*
* 格式说明:
* yyyy - 4位年份
* MM - 2位月份 (01-12)
* dd - 2位日期 (01-31)
* HH - 24小时制小时 (00-23)
* mm - 分钟 (00-59)
* ss - 秒 (00-59)
* EEE - 星期几 (Mon, Tue, ...)
* EEEE - 完整星期 (Monday, Tuesday, ...)
*/
static format(date: Date, format: string): string {
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const hour = date.getHours();
const minute = date.getMinutes();
const second = date.getSeconds();
const weekday = date.getDay();
const weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
const weekdaysShort = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
let result = format;
result = result.replace(/yyyy/g, year.toString());
result = result.replace(/MM/g, this.padZero(month));
result = result.replace(/dd/g, this.padZero(day));
result = result.replace(/HH/g, this.padZero(hour));
result = result.replace(/mm/g, this.padZero(minute));
result = result.replace(/ss/g, this.padZero(second));
result = result.replace(/EEEE/g, weekdays[weekday]);
result = result.replace(/EEE/g, weekdaysShort[weekday]);
return result;
}
/**
* 解析日期字符串
* [@param](/user/param) dateString 日期字符串
* [@param](/user/param) format 日期格式(可选)
* [@returns](/user/returns) Date对象
*/
static parse(dateString: string, format?: string): Date | null {
if (format) {
// 简单解析,支持常见格式
return this.parseWithFormat(dateString, format);
}
// 尝试标准格式
const date = new Date(dateString);
return isNaN(date.getTime()) ? null : date;
}
/**
* 根据格式解析日期
*/
private static parseWithFormat(dateString: string, format: string): Date | null {
// 简化实现,支持 yyyy-MM-dd 和 yyyy-MM-dd HH:mm:ss
const ymdMatch = dateString.match(/(\d{4})-(\d{2})-(\d{2})/);
if (ymdMatch) {
const year = parseInt(ymdMatch[1]);
const month = parseInt(ymdMatch[2]) - 1;
const day = parseInt(ymdMatch[3]);
const hmsMatch = dateString.match(/(\d{2}):(\d{2}):(\d{2})/);
if (hmsMatch) {
const hour = parseInt(hmsMatch[1]);
const minute = parseInt(hmsMatch[2]);
const second = parseInt(hmsMatch[3]);
return new Date(year, month, day, hour, minute, second);
}
return new Date(year, month, day);
}
return null;
}
/**
* 获取日期组件
*/
static getComponents(date: Date): DateComponents {
return {
year: date.getFullYear(),
month: date.getMonth() + 1,
day: date.getDate(),
hour: date.getHours(),
minute: date.getMinutes(),
second: date.getSeconds(),
millisecond: date.getMilliseconds(),
weekday: date.getDay() + 1 // 1-7, 1=Sunday
};
}
/**
* 从组件创建日期
*/
static fromComponents(components: DateComponents): Date {
return new Date(
components.year,
components.month - 1,
components.day,
components.hour || 0,
components.minute || 0,
components.second || 0,
components.millisecond || 0
);
}
/**
* 日期加法
*/
static add(date: Date, unit: 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second', value: number): Date {
const newDate = new Date(date);
switch (unit) {
case 'year':
newDate.setFullYear(newDate.getFullYear() + value);
break;
case 'month':
newDate.setMonth(newDate.getMonth() + value);
break;
case 'day':
newDate.setDate(newDate.getDate() + value);
break;
case 'hour':
newDate.setHours(newDate.getHours() + value);
break;
case 'minute':
newDate.setMinutes(newDate.getMinutes() + value);
break;
case 'second':
newDate.setSeconds(newDate.getSeconds() + value);
break;
}
return newDate;
}
/**
* 日期减法
*/
static subtract(date: Date, unit: 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second', value: number): Date {
return this.add(date, unit, -value);
}
/**
* 计算两个日期之间的差值
*/
static diff(start: Date, end: Date, unit: 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond'): number {
const diffMs = end.getTime() - start.getTime();
switch (unit) {
case 'millisecond':
return diffMs;
case 'second':
return Math.floor(diffMs / 1000);
case 'minute':
return Math.floor(diffMs / (1000 * 60));
case 'hour':
return Math.floor(diffMs / (1000 * 60 * 60));
case 'day':
return Math.floor(diffMs / (1000 * 60 * 60 * 24));
case 'month':
return (end.getFullYear() - start.getFullYear()) * 12 + (end.getMonth() - start.getMonth());
case 'year':
return end.getFullYear() - start.getFullYear();
default:
return diffMs;
}
}
/**
* 相对时间描述(如"2小时前")
*/
static timeAgo(date: Date, now: Date = new Date()): string {
const diffSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);
if (diffSeconds < 0) {
return this.timeUntil(date, now);
}
if (diffSeconds < 60) {
return diffSeconds <= 1 ? '刚刚' : `${diffSeconds}秒前`;
}
const diffMinutes = Math.floor(diffSeconds / 60);
if (diffMinutes < 60) {
return `${diffMinutes}分钟前`;
}
const diffHours = Math.floor(diffMinutes / 60);
if (diffHours < 24) {
return `${diffHours}小时前`;
}
const diffDays = Math.floor(diffHours / 24);
if (diffDays < 7) {
return `${diffDays}天前`;
}
const diffWeeks = Math.floor(diffDays / 7);
if (diffWeeks < 4) {
return `${diffWeeks}周前`;
}
const diffMonths = Math.floor(diffDays / 30);
if (diffMonths < 12) {
return `${diffMonths}个月前`;
}
const diffYears = Math.floor(diffDays / 365);
return `${diffYears}年前`;
}
/**
* 未来时间描述(如"2小时后")
*/
static timeUntil(date: Date, now: Date = new Date()): string {
const diffSeconds = Math.floor((date.getTime() - now.getTime()) / 1000);
if (diffSeconds < 0) {
return this.timeAgo(date, now);
}
if (diffSeconds < 60) {
return diffSeconds <= 1 ? '即将' : `${diffSeconds}秒后`;
}
const diffMinutes = Math.floor(diffSeconds / 60);
if (diffMinutes < 60) {
return `${diffMinutes}分钟后`;
}
const diffHours = Math.floor(diffMinutes / 60);
if (diffHours < 24) {
return `${diffHours}小时后`;
}
const diffDays = Math.floor(diffHours / 24);
if (diffDays < 7) {
return `${diffDays}天后`;
}
const diffWeeks = Math.floor(diffDays / 7);
if (diffWeeks < 4) {
return `${diffWeeks}周后`;
}
const diffMonths = Math.floor(diffDays / 30);
if (diffMonths < 12) {
return `${diffMonths}个月后`;
}
const diffYears = Math.floor(diffDays / 365);
return `${diffYears}年后`;
}
/**
* 判断是否为今天
*/
static isToday(date: Date): boolean {
const today = new Date();
return date.getDate() === today.getDate() &&
date.getMonth() === today.getMonth() &&
date.getFullYear() === today.getFullYear();
}
/**
* 判断是否为昨天
*/
static isYesterday(date: Date): boolean {
const yesterday = this.subtract(new Date(), 'day', 1);
return date.getDate() === yesterday.getDate() &&
date.getMonth() === yesterday.getMonth() &&
date.getFullYear() === yesterday.getFullYear();
}
/**
* 判断是否为明天
*/
static isTomorrow(date: Date): boolean {
const tomorrow = this.add(new Date(), 'day', 1);
return date.getDate() === tomorrow.getDate() &&
date.getMonth() === tomorrow.getMonth() &&
date.getFullYear() === tomorrow.getFullYear();
}
/**
* 判断是否为本周
*/
static isThisWeek(date: Date): boolean {
const now = new Date();
const weekStart = this.startOfWeek(now);
const weekEnd = this.endOfWeek(now);
return date >= weekStart && date <= weekEnd;
}
/**
* 判断是否为本月
*/
static isThisMonth(date: Date): boolean {
const now = new Date();
return date.getMonth() === now.getMonth() &&
date.getFullYear() === now.getFullYear();
}
/**
* 判断是否为今年
*/
static isThisYear(date: Date): boolean {
const now = new Date();
return date.getFullYear() === now.getFullYear();
}
/**
* 获取周的开始日期
*/
static startOfWeek(date: Date, firstDayOfWeek: number = 0): Date {
const d = new Date(date);
const day = d.getDay();
const diff = (day < firstDayOfWeek ? 7 : 0) + day - firstDayOfWeek;
d.setDate(d.getDate() - diff);
d.setHours(0, 0, 0, 0);
return d;
}
/**
* 获取周的结束日期
*/
static endOfWeek(date: Date, firstDayOfWeek: number = 0): Date {
const start = this.startOfWeek(date, firstDayOfWeek);
const end = new Date(start);
end.setDate(end.getDate() + 6);
end.setHours(23, 59, 59, 999);
return end;
}
/**
* 获取月的开始日期
*/
static startOfMonth(date: Date): Date {
return new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0, 0);
}
/**
* 获取月的结束日期
*/
static endOfMonth(date: Date): Date {
return new Date(date.getFullYear(), date.getMonth() + 1, 0, 23, 59, 59, 999);
}
/**
* 获取年的开始日期
*/
static startOfYear(date: Date): Date {
return new Date(date.getFullYear(), 0, 1, 0, 0, 0, 0);
}
/**
* 获取年的结束日期
*/
static endOfYear(date: Date): Date {
return new Date(date.getFullYear(), 11, 31, 23, 59, 59, 999);
}
/**
* 比较两个日期
* [@returns](/user/returns) -1: date1 < date2, 0: date1 == date2, 1: date1 > date2
*/
static compare(date1: Date, date2: Date): number {
const time1 = date1.getTime();
const time2 = date2.getTime();
if (time1 < time2) return -1;
if (time1 > time2) return 1;
return 0;
}
/**
* 判断日期是否在范围内
*/
static isInRange(date: Date, range: DateRange): boolean {
return date >= range.start && date <= range.end;
}
/**
* 获取日期范围
*/
static range(start: Date, end: Date): DateRange {
return {
start: start < end ? start : end,
end: start < end ? end : start
};
}
/**
* 获取两个日期之间的所有日期
*/
static datesBetween(start: Date, end: Date): Date[] {
const dates: Date[] = [];
const current = new Date(start);
current.setHours(0, 0, 0, 0);
const endDate = new Date(end);
endDate.setHours(0, 0, 0, 0);
while (current <= endDate) {
dates.push(new Date(current));
current.setDate(current.getDate() + 1);
}
return dates;
}
/**
* 获取年龄
*/
static age(birthDate: Date, referenceDate: Date = new Date()): number {
let age = referenceDate.getFullYear() - birthDate.getFullYear();
const monthDiff = referenceDate.getMonth() - birthDate.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && referenceDate.getDate() < birthDate.getDate())) {
age--;
}
return age;
}
/**
* 获取工作日数量(排除周末)
*/
static weekdaysBetween(start: Date, end: Date): number {
let count = 0;
const current = new Date(start);
current.setHours(0, 0, 0, 0);
const endDate = new Date(end);
endDate.setHours(0, 0, 0, 0);
while (current <= endDate) {
const day = current.getDay();
if (day !== 0 && day !== 6) { // 排除周日和周六
count++;
}
current.setDate(current.getDate() + 1);
}
return count;
}
/**
* 获取下一个工作日
*/
static nextWeekday(date: Date): Date {
let next = this.add(date, 'day', 1);
while (next.getDay() === 0 || next.getDay() === 6) {
next = this.add(next, 'day', 1);
}
return next;
}
/**
* 获取上一个工作日
*/
static previousWeekday(date: Date): Date {
let prev = this.subtract(date, 'day', 1);
while (prev.getDay() === 0 || prev.getDay() === 6) {
prev = this.subtract(prev, 'day', 1);
}
return prev;
}
/**
* 格式化相对时间(智能显示)
*/
static smartFormat(date: Date, now: Date = new Date()): string {
if (this.isToday(date)) {
return `今天 ${this.format(date, 'HH:mm')}`;
} else if (this.isYesterday(date)) {
return `昨天 ${this.format(date, 'HH:mm')}`;
} else if (this.isTomorrow(date)) {
return `明天 ${this.format(date, 'HH:mm')}`;
} else if (this.isThisWeek(date)) {
return `${this.format(date, 'EEE')} ${this.format(date, 'HH:mm')}`;
} else if (this.isThisYear(date)) {
return this.format(date, 'MM-dd HH:mm');
} else {
return更多关于HarmonyOS鸿蒙Next中类似于swiftDate的日期时间操作库的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,推荐使用内置的日期时间处理库@ohos.util.DateTime。该库提供了日期时间的创建、格式化、计算和比较等功能。例如,可以使用DateTime类进行日期时间的加减操作,Time类处理时间相关的计算。此外,@ohos.i18n中的Calendar类支持农历和节假日等高级功能。这些API均基于TypeScript/ArkTS开发,符合鸿蒙应用开发规范。
在HarmonyOS Next中,你可以通过ArkTS的日期时间处理能力,结合扩展封装来实现类似SwiftDate的便捷操作。目前虽然没有完全对等的第三方库,但可以通过以下方式构建:
-
使用内置Date对象:ArkTS提供了标准的Date API,支持日期计算、格式化等基础操作。
-
封装工具类:建议创建一个DateTime工具类,集成常用功能:
- 日期解析(支持多种格式字符串)
- 相对时间计算(如加减天数、月份)
- 人性化时间显示(如“刚刚”、“3天前”)
- 时区转换支持
-
关键实现示例:
// 示例:基础日期操作封装
class DateTimeUtils {
static addDays(date: Date, days: number): Date {
let result = new Date(date);
result.setDate(result.getDate() + days);
return result;
}
static formatRelative(date: Date): string {
// 实现相对时间逻辑
}
}
- 考虑使用扩展方法:通过扩展Date原型或提供静态工具类来增强可读性。
HarmonyOS Next的ArkTS在类型安全和性能方面有良好支持,适合构建这类工具库。建议先明确核心需求,再逐步实现常用功能模块。

