news 2026/7/20 12:46:53

HarmonyOs应用《重要日》开发第26篇 - 基于 dayjs 的日期处理方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HarmonyOs应用《重要日》开发第26篇 - 基于 dayjs 的日期处理方案

本文解析 ImportantDays 项目中 dayjs 库的使用方式,包括 dayjs 的引入、在 DateUtil/DateModel/CalendarVM 中的应用场景、与原生 Date 对象的互转,以及 dayjs 在鸿蒙 ArkTS 环境中的实践要点。

一、dayjs 简介

dayjs 是一个轻量级的 JavaScript 日期库,API 设计与 moment.js 兼容,但体积仅 2KB。

核心特性

特性说明
轻量2KB(gzip 后)
不可变所有操作返回新对象
链式调用dayjs().add(1, 'day').format('YYYY-MM-DD')
插件系统可按需引入功能

二、项目中的引入

oh-package.json5 依赖

{"dependencies":{"dayjs":"^1.11.x"}}

导入方式

// DateUtil.etsimportdayjsfrom'dayjs';// DateModel.etsimportdayjsfrom'dayjs';// CalendarVM.etsimportdayjsfrom'dayjs';// MonthWeekCalendar.etsimportdayjsfrom'dayjs';// CalendarPage.etsimportdayjsfrom'dayjs';// BaseCalendar.etsimportdayjsfrom'dayjs';

项目中有 6 个文件导入了 dayjs,覆盖了所有需要日期处理的模块。

三、dayjs 在 DateUtil 中的应用

格式化

staticgetFormatDate(date:Date|dayjs.Dayjs):string{returndayjs(date).format('YYYY-MM-DD');}staticgetFullDateStr(date:Date):string{returndayjs(date).format('YYYY年MM月DD日');}staticgetDateTimeStr(date:Date):string{returndayjs(date).format('YYYY-MM-DD HH:mm');}

常用格式化占位符

占位符含义示例
YYYY四位年份2026
MM两位月份07
DD两位日期17
HH24小时制23
mm分钟07
ss00

日期判断

staticisToday(date:Date|dayjs.Dayjs):boolean{returndayjs(date).isSame(dayjs(),'day');}

isSame的第二个参数指定比较粒度:

  • 'day':比较到天
  • 'month':比较到月
  • 'year':比较到年

获取月份天数

staticgetDaysByMonth(year:number,month:number):number{returndayjs().year(year).month(month).daysInMonth();}

daysInMonth()自动处理闰年:

  • dayjs().year(2024).month(1).daysInMonth()→ 29(闰年二月)
  • dayjs().year(2025).month(1).daysInMonth()→ 28(平年二月)

星期名称

staticgetWeekdayName(date:Date|dayjs.Dayjs):string{constnames=['周日','周一','周二','周三','周四','周五','周六'];returnnames[dayjs(date).day()];}

dayjs().day()返回 0-6(0=周日)。

日期键生成

staticbuildKeyByDate(date:Date|dayjs.Dayjs):string{returndayjs(date).format('YYYY-MM-DD');}

日期范围

staticgetDateRangeKeys(startDate:Date,endDate:Date):string[]{constkeys:string[]=[];conststart=dayjs(startDate);constend=dayjs(endDate);letcurrent=start;while(current.isBefore(end)||current.isSame(end,'day')){keys.push(current.format('YYYY-MM-DD'));current=current.add(1,'day');}returnkeys;}

使用isBefore+isSame组合判断范围边界,add(1, 'day')递增日期。

四、dayjs 在 DateModel 中的应用

exportclassDateModel{dayjsObj:dayjs.Dayjs;day:number;lunarDay:string;isCurrentMonth:boolean;dateStr:string;constructor(dayjsObj:dayjs.Dayjs,isCurrentMonth:boolean=true){this.dayjsObj=dayjsObj;this.day=dayjsObj.date();// 获取日期数字this.lunarDay='';this.isCurrentMonth=isCurrentMonth;this.dateStr=dayjsObj.format('YYYY-MM-DD');// 预生成日期键}}

设计要点

  1. 存储 dayjs 对象dayjsObj保存原始 dayjs 对象,便于后续操作
  2. 预计算属性daydateStr在构造时预计算,避免渲染时重复调用
  3. 农历预留lunarDay预留农历字段(当前为空)

五、dayjs 在 CalendarVM 中的应用

当前日期

@TraceselectDate:dayjs.Dayjs=dayjs();

使用dayjs()获取当前时间作为初始选中日期。

月份数据生成

getDateList(date:dayjs.Dayjs):DateModelList{constyear=date.year();constmonth=date.month();constfirstDay=dayjs().year(year).month(month).date(1);constdaysInMonth=date.daysInMonth();letfirstDayWeekday:number=firstDay.day();firstDayWeekday=(firstDayWeekday-this.startWeekday+WEEK_DAYS)%WEEK_DAYS;// 上月填充for(leti=firstDayWeekday-1;i>=0;i--){constprevDate=firstDay.subtract(i+1,'day');list.push(newDateModel(prevDate,false));}// 当月for(leti=1;i<=daysInMonth;i++){constdayDate=dayjs().year(year).month(month).date(i);list.push(newDateModel(dayDate,true));}// 下月填充while(list.length<42){constlastDate=list[list.length-1].dayjsObj;constnextDate=lastDate.add(1,'day');list.push(newDateModel(nextDate,false));}returnlist;}

dayjs 链式操作

dayjs().year(year).month(month).date(1)

创建指定年月的第一天:

  1. dayjs()获取当前时间
  2. .year(year)设置年份
  3. .month(month)设置月份
  4. .date(1)设置为1号

日期加减

firstDay.subtract(i+1,'day')// 向前推 i+1 天lastDate.add(1,'day')// 向后推 1 天

subtractadd的第二个参数支持:dayweekmonthyearhourminutesecond

初始化数据

privateinitCalendarData():void{this.monthWeekDataSource.clearData();for(leti=-1;i<=1;i++){constdate=dayjs().add(i,'month');// 当前月 ± ithis.monthWeekDataSource.addData(this.getDateList(date));}}

日期导航

goToToday():void{this.selectDate=dayjs();this.initCalendarData();}getCurrentMonthTitle():string{returnthis.selectDate.format('YYYY年MM月');}getCurrentYearTitle():string{return`${this.selectDate.year()}`;}

日期比较

isToday(date:dayjs.Dayjs):boolean{returndate.isSame(dayjs(),'day');}isDateSelect(date:dayjs.Dayjs):boolean{returndate.isSame(this.selectDate,'day');}

六、dayjs 在组件中的应用

CalendarPage 中的日期操作

// 上一月this.vm.selectDate=this.vm.selectDate.subtract(1,'month');// 下一月this.vm.selectDate=this.vm.selectDate.add(1,'month');// 日期选择器回调constdate=dayjs().year(value.year).month(value.month).date(value.day);this.vm.changeDate(date);// 格式化this.selectDate.format('YYYY-MM-DD')

MonthWeekCalendar 中的日期比较

// 月份比较if(!this.vm.selectDate.isSame(middleDate,'month')){this.vm.selectDate=middleDate;}

BaseCalendar 中的日期操作

privategetDateList():DateModel[]{constdate=dayjs().year(this.year).month(this.month);constfirstDay=date.date(1);constdaysInMonth=date.daysInMonth();// ...}

七、dayjs 与 Date 的互转

Date → dayjs

constd=newDate();constdj=dayjs(d);// Date → dayjs

dayjs → Date

constdj=dayjs();constd=dj.toDate();// dayjs → Date

项目中的互转场景

// CalendarPage 中 DatePicker 回调.onChange((value:DatePickerResult)=>{constdate=dayjs().year(value.year).month(value.month).date(value.day);this.vm.changeDate(date);// 传入 dayjs})// MonthWeekCalendar 中日期点击privateonDateClick(dateModel:DateModel):void{this.vm.changeDate(dateModel.dayjsObj);// 传入 dayjsthis.onChangeDay(dateModel.dayjsObj.toDate());// 传入 Date}

八、dayjs 的不可变性

不可变操作

consttoday=dayjs();consttomorrow=today.add(1,'day');console.log(today.format('YYYY-MM-DD'));// 2026-07-17(不变)console.log(tomorrow.format('YYYY-MM-DD'));// 2026-07-18(新对象)

addsubtract等操作不修改原对象,而是返回新对象。

与原生 Date 的对比

// 原生 Date(可变)constd=newDate('2026-07-17');d.setDate(d.getDate()+1);console.log(d);// 2026-07-18(原对象被修改)// dayjs(不可变)constdj=dayjs('2026-07-17');constnext=dj.add(1,'day');console.log(dj.format('YYYY-MM-DD'));// 2026-07-17(不变)console.log(next.format('YYYY-MM-DD'));// 2026-07-18(新对象)

不可变性在状态管理中非常重要——避免了意外修改导致的状态混乱。

九、性能考量

dayjs 对象创建

// 日历渲染中会创建大量 dayjs 对象for(leti=1;i<=daysInMonth;i++){constdayDate=dayjs().year(year).month(month).date(i);list.push(newDateModel(dayDate,true));}

每月创建约 42 个 dayjs 对象,年视图创建 12 × 42 = 504 个。dayjs 对象很轻量,这个数量级不会有性能问题。

预计算优化

constructor(dayjsObj:dayjs.Dayjs,isCurrentMonth:boolean=true){this.dayjsObj=dayjsObj;this.day=dayjsObj.date();// 预计算this.dateStr=dayjsObj.format('YYYY-MM-DD');// 预计算}

DateModel预计算了daydateStr,避免渲染时重复调用 dayjs 方法。

十、总结

dayjs 在 ImportantDays 项目中的使用体现了以下实践:

  1. 统一工具类DateUtil封装所有 dayjs 操作
  2. 双类型兼容:方法接受Date | dayjs.Dayjs
  3. 预计算优化DateModel预计算常用属性
  4. 不可变操作:利用 dayjs 不可变性保障状态安全
  5. 链式调用dayjs().year().month().date()简洁高效
  6. 灵活格式化format()支持各种日期格式

dayjs 以极小的代价为项目提供了强大的日期处理能力,是鸿蒙应用中日期处理的首选方案。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/20 12:46:51

3分钟快速上手:DDGS元搜索库让你的搜索能力提升10倍

3分钟快速上手&#xff1a;DDGS元搜索库让你的搜索能力提升10倍 【免费下载链接】ddgs A metasearch library that aggregates results from diverse web search services 项目地址: https://gitcode.com/GitHub_Trending/du/ddgs DDGS&#xff08;Dux Distributed Glob…

作者头像 李华
网站建设 2026/7/20 12:46:29

时空时序推理框架STReasoner:解决因果盲区与结构无视问题

1. 时空时序推理框架的行业痛点与突破在交通管理、电力调度、疫情传播分析等领域&#xff0c;我们每天面对海量的传感器数据——这些数据不仅随时间变化&#xff08;时序性&#xff09;&#xff0c;还受到地理空间关系的制约&#xff08;空间性&#xff09;。传统的时间序列预测…

作者头像 李华
网站建设 2026/7/20 12:46:20

Amphenol ICC DRPC51A003A40连接方案与国产替代方向

随着电子设备向高性能、高集成和模块化方向不断发展&#xff0c;线束线缆组件已经从简单的连接部件逐渐成为影响设备可靠性的重要基础组件。无论是在通信设备、工业控制系统&#xff0c;还是服务器、新能源电子等领域&#xff0c;高质量线束方案都承担着信号传输、电源连接以及…

作者头像 李华
网站建设 2026/7/20 12:46:13

110-基于51单片机金属探测器【Proteus仿真+Keil程序+报告+原理图】

110-基于51单片机金属探测器一、系统硬件整体方案 本金属探测报警系统以STC89C51单片机为控制核心&#xff0c;搭配单片机最小系统。外围硬件包含LCD1602液晶显示模块、AT24C02存储芯片、三点式振荡感应电路、LM393电压比较器、功能按键、蜂鸣器与LED状态指示灯。系统通过电磁感…

作者头像 李华
网站建设 2026/7/20 12:45:55

深入解析TI Jacinto EVE寄存器:从映射原理到汽车视觉应用实战

1. 深入理解EVE子系统寄存器映射在嵌入式视觉处理领域&#xff0c;尤其是像德州仪器&#xff08;TI&#xff09;Jacinto 6 Plus这样的高性能SoC平台上&#xff0c;寄存器是软件工程师与硬件直接对话的“语言”。它远不止是技术手册里那一张张枯燥的表格&#xff0c;而是你掌控整…

作者头像 李华