news 2026/7/24 13:19:33

HarmonyOS 应用开发《掌上英语》第43篇:日期与时间处理——ArkTS 中的时间工具

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HarmonyOS 应用开发《掌上英语》第43篇:日期与时间处理——ArkTS 中的时间工具

日期与时间处理——ArkTS 中的时间工具

一、时间处理的常见需求

在英语学习应用中,时间处理无处不在:

  • 记录生词添加时间、答题时间戳
  • 判断"今天"是否已经学习过
  • 计算连续学习天数
  • 生成每日挑战题目的种子
  • 周维度统计数据的日期计算

ArkTS 基于标准 ECMAScript,提供了完整的Date对象 API。本文将通过项目中的实际源码,展示常见的日期时间处理模式。

二、核心 Date 对象用法

2.1 获取当前时间戳

Date.now()返回距 1970 年 1 月 1 日的毫秒数,是最常用的时间记录方式:

// NewWordManager 中记录添加时间addTime:Date.now()// AnswerQuestionsPage 中记录答题时间戳currentItem.jlStamp=Date.now();

2.2 格式化日期字符串

将 Date 对象转为YYYY-MM-DD格式的字符串,用于"某天的数据"的键值判断:

// DailyChallengeManager 中获取今天的日期字符串privategetTodayStr():string{letnow=newDate();letyear=now.getFullYear();letmonth=(now.getMonth()+1).toString().padStart(2,'0');letday=now.getDate().toString().padStart(2,'0');return`${year}-${month}-${day}`;}

这段代码有几点值得注意:

  • getMonth()返回 0~11,所以需要+1
  • padStart(2, '0')确保月份和日期始终为两位数
  • 使用模板字符串拼接,比+连接更清晰

2.3 时间戳清零(归零到当天 0 点)

在比较是否为同一天时,需要先将时间戳归零到当天 0 点:

// LearningPlanManager 中的关键操作lettoday=newDate();today.setHours(0,0,0,0);// 设置为当天 00:00:00.000lettodayTimestamp=today.getTime();

setHours(0, 0, 0, 0)将时、分、秒、毫秒全部归零,这样比较两个 Date 对象的getTime()就能判断它们是否在同一天。

三、LearningPlanManager 中的日期计算

checkAndUpdateContinuousDays方法展示了完整的天数计算逻辑:

publiccheckAndUpdateContinuousDays():LearningPlan{letplan=this.getLearningPlan();lettoday=newDate();today.setHours(0,0,0,0);lettodayTimestamp=today.getTime();if(plan.lastStudyDate===0){// 首次学习plan.continuousDays=1;}else{letlastDate=newDate(plan.lastStudyDate);lastDate.setHours(0,0,0,0);letlastTimestamp=lastDate.getTime();letdiffDays=Math.floor((todayTimestamp-lastTimestamp)/(1000*60*60*24));if(diffDays===0){// 同一天,不更新}elseif(diffDays===1){// 连续plan.continuousDays++;}else{// 中断,重置plan.continuousDays=1;}}plan.lastStudyDate=todayTimestamp;this.saveLearningPlan(plan);returnplan;}

3.1 天数差计算

letdiffDays=Math.floor((todayTimestamp-lastTimestamp)/(1000*60*60*24));

这个公式的原理:

  • 两个时间戳相减得到毫秒差
  • 1000 * 60 * 60 * 24是一天的毫秒数
  • Math.floor向下取整,确保跨天判断准确

3.2 连续天数的三种状态

diffDays含义操作
0同一天不更新(防止重复打卡增加天数)
1连续continuousDays++
>1中断重置为 1

四、DailyChallengeManager 中的种子算法

每日挑战需要确保:同一天内题目固定不变,不同天题目不同。这通过日期字符串生成随机种子来实现:

generateDailyChallenge(allQuestions:TopicItemType[]):void{lettodayStr=this.getTodayStr();// 已存在当日题目,直接复用letexistingQuestions=this.challengeQuestions;if(existingQuestions.length===5&&this.todayCompleted===false){letfirstKey=existingQuestions.length>0?existingQuestions[0].keyID:'';letdateSeed=todayStr.split('-').join('');if(firstKey.startsWith('DC_'+dateSeed)){return;}}// 用日期字符串生成种子letseed=0;for(leti=0;i<todayStr.length;i++){seed=seed*31+todayStr.charCodeAt(i);}seed=Math.abs(seed);// 基于种子的 Fisher-Yates 洗牌letcount=Math.min(5,allQuestions.length);letselected:TopicItemType[]=[];letindices:number[]=[];for(leti=0;i<allQuestions.length;i++){indices.push(i);}for(leti=indices.length-1;i>0;i--){seed=(seed*16807+7)%2147483647;letj=seed%(i+1);lettemp=indices[i];indices[i]=indices[j];indices[j]=temp;}// ...}

这里的种子算法是:将日期字符串"2026-07-08"的每个字符的 charCode 累加乘 31,生成一个固定的种子。然后用线性同余法(seed = (seed * 16807 + 7) % 2147483647)生成伪随机序列。

五、统计模块中的周日期计算

DashboardManager 在构建周度数据时需要回溯前 6 天:

privatebuildWeeklyData(plan:LearningPlan):DailyStats[]{letresult:DailyStats[]=[];letdayLabels:string[]=['周日','周一','周二','周三','周四','周五','周六'];lettoday=newDate();today.setHours(0,0,0,0);for(leti=6;i>=0;i--){letd=newDate(today.getTime()-i*24*60*60*1000);letdateStr=(d.getMonth()+1).toString()+'/'+d.getDate().toString();letdayLabel=dayLabels[d.getDay()];// ...}}

核心技巧:new Date(today.getTime() - i * 24 * 60 * 60 * 1000)通过一天天的毫秒数偏移获取前几天的日期。这比setDate(getDate() - 1)更直观。

六、日期格式化的其他方式

6.1 笔记添加时间

// AnswerQuestionsPage 中记录笔记时间this.topicItemModelPref.addNoteTime=newDate().getTime();

6.2 打卡日历月份判断

getCheckInCalendarMonth(year:number,month:number):boolean[]{letresult:boolean[]=newArray(31).fill(false)asboolean[];letmonthStr=`${year}-${month.toString().padStart(2,'0')}-`;for(leti=0;i<this.checkInDays.length;i++){if(this.checkInDays[i].startsWith(monthStr)){letdayStr=this.checkInDays[i].substring(monthStr.length);letday=parseInt(dayStr,10);if(day>=1&&day<=31){result[day-1]=true;}}}returnresult;}

利用已存储的YYYY-MM-DD格式字符串,通过startsWithsubstring精确判断某月某日是否打过卡。

七、时间处理最佳实践

  1. 统一使用时间戳Date.now()date.getTime()存储,避免时区问题
  2. 比较前清零:判断是否为同一天时,统一setHours(0,0,0,0)后再比较
  3. 格式化字符串:用于显示时再格式化,推荐YYYY-MM-DD格式
  4. 避免直接操作 Date 字符串:优先使用时间戳计算差值,最后再转为字符串

ArkTS 的 Date API 与标准 JavaScript 保持一致,掌握这些模式后,任何与时间相关的业务需求都能迎刃而解。

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

Linux apt 命令

1. 什么是 apt 命令&#xff1f; apt&#xff08;Advanced Packaging Tool&#xff09;是 Debian 和 Ubuntu 系统中的 Shell 前端软件包管理器。它提供了查找、安装、升级、删除软件包的简洁命令&#xff0c;大大简化了软件包管理流程。apt 命令执行需要超级管理员权限&#xf…

作者头像 李华
网站建设 2026/7/24 13:18:51

C++从零构建游戏导航网格:原理、实现与工程实践

1. 项目概述&#xff1a;为什么导航网格是游戏AI的基石 在游戏开发&#xff0c;尤其是涉及复杂地形和大量AI角色的项目中&#xff0c;如何让一个虚拟角色智能地从A点移动到B点&#xff0c;同时避开障碍物、选择最优路径&#xff0c;是一个核心挑战。这就是游戏导航系统要解决的…

作者头像 李华
网站建设 2026/7/24 13:13:35

深入解析TI TPS25740B USB PD控制器:从协议到实战设计

1. 项目概述&#xff1a;为什么我们需要一颗专用的USB PD控制器&#xff1f;如果你最近拆解过任何一款支持USB Type-C充电的笔记本电脑电源适配器、显示器或者高端手机充电器&#xff0c;大概率会在其主板上看到一颗或几颗不起眼的“小黑块”——USB PD控制器。这玩意儿是干什么…

作者头像 李华
网站建设 2026/7/24 13:08:30

RAG技术解析:大模型应用开发实战指南

1. RAG技术在大模型应用开发中的核心价值RAG&#xff08;Retrieval-Augmented Generation&#xff09;技术正在重塑大模型应用的开发范式。作为从业者&#xff0c;我亲历了从纯Prompt工程到RAG架构的转变过程。这种技术通过将信息检索与文本生成相结合&#xff0c;有效解决了大…

作者头像 李华
网站建设 2026/7/24 13:08:10

2026视频去水印软件哪个好用?手机电脑AI工具与风险详解

日常整理个人短视频素材、清理自有作品平台水印、归档已授权视频物料时&#xff0c;很多人都会纠结工具选择问题。2026年市面上的视频去水印工具分为手机端APP、电脑端专业软件、在线网站、免安装小程序四大类&#xff0c;不同工具的操作难度、处理效果、隐私安全性差异极大。其…

作者头像 李华