HarmonyOS 鸿蒙Next中使用 Date 实现高精度毫秒级秒表

HarmonyOS 鸿蒙Next中使用 Date 实现高精度毫秒级秒表 如何使用 Date 实现高精度毫秒级秒表应用?以此来实现跑步计时?

3 回复

实现效果

实现效果

使用场景

跑步、游泳计圈、定时闹钟等

实现思路

第一步:创建一个HighPrecisionStopwatch管理方法类,维护一个 elapsedTime,定时器每次触发时,elapsedTime += 10。

第二步:通过lapTimes一个数组来 管理日期记录以此来实现圈数数据的记录。

完整实现代码

import { hilog } from '@kit.PerformanceAnalysisKit';

export class HighPrecisionStopwatch {
  private startTime: number = 0;
  private elapsedTime: number = 0;
  private isRunning: boolean = false;
  private lapTimes: number[] = [];

  // 开始计时
  start(): void {
    if (!this.isRunning) {
      this.startTime = Date.now() - this.elapsedTime;
      this.isRunning = true;
      hilog.info(0x0000, 'Stopwatch', '秒表开始计时');
    }
  }

  // 暂停计时
  pause(): void {
    if (this.isRunning) {
      this.elapsedTime = Date.now() - this.startTime;
      this.isRunning = false;
      hilog.info(0x0000, 'Stopwatch', `秒表暂停,当前时间: ${this.getFormattedTime()}`);
    }
  }

  // 记录单圈时间
  lap(): string {
    if (this.isRunning) {
      const currentTime = Date.now();
      const lapTime = currentTime - this.startTime;
      this.lapTimes.push(lapTime);

      const formattedLap = this.formatMilliseconds(lapTime);
      hilog.info(0x0000, 'Stopwatch', `单圈时间: ${formattedLap}`);
      return formattedLap;
    }
    return '00:00:00.000';
  }

  // 重置秒表
  reset(): void {
    this.startTime = 0;
    this.elapsedTime = 0;
    this.isRunning = false;
    this.lapTimes = [];
    hilog.info(0x0000, 'Stopwatch', '秒表已重置');
  }

  // 获取当前时间(毫秒)
  getCurrentTime(): number {
    if (this.isRunning) {
      return Date.now() - this.startTime;
    }
    return this.elapsedTime;
  }

  // 格式化时间显示
  getFormattedTime(): string {
    const time = this.getCurrentTime();
    return this.formatMilliseconds(time);
  }

  // 毫秒格式化
  private formatMilliseconds(ms: number): string {
    const hours = Math.floor(ms / 3600000);
    const minutes = Math.floor((ms % 3600000) / 60000);
    const seconds = Math.floor((ms % 60000) / 1000);
    const milliseconds = Math.floor(ms % 1000);

    return `${hours.toString().padStart(2, '0')}:${
    minutes.toString().padStart(2, '0')}:${
    seconds.toString().padStart(2, '0')}.${
    milliseconds.toString().padStart(3, '0')}`;
  }

  // 获取所有单圈时间
  getAllLaps(): string[] {
    return this.lapTimes.map((lap, index) =>
    `单圈 ${index + 1}: ${this.formatMilliseconds(lap)}`
    );
  }
}
import { HighPrecisionStopwatch } from './HighPrecisionStopwatch';

@Entry
@Component
struct StopwatchPage {
  private stopwatch: HighPrecisionStopwatch = new HighPrecisionStopwatch();
  @State currentTime: string = '00:00:00.000';
  @State laps: string[] = [];
  private timerId: number = 0;

  aboutToAppear(): void {
    this.startTimer();
  }

  aboutToDisappear(): void {
    this.stopTimer();
  }

  // 定时更新UI
  startTimer(): void {
    this.timerId = setInterval(() => {
      if (this.stopwatch) {
        this.currentTime = this.stopwatch.getFormattedTime();
      }
    }, 10);
  }

  stopTimer(): void {
    if (this.timerId) {
      clearInterval(this.timerId);
    }
  }

  build() {
    Column({ space: 0 }) {
      // 时间显示
      Text(this.currentTime)
        .fontSize(48)
        .fontWeight(FontWeight.Bold)
        .fontColor(Color.Black)
        .margin({ top: 50 })

      // 控制按钮
      Row({ space: 10 }) {
        Button('开始')
          .backgroundColor('#007DFF')
          .onClick(() => {
            this.stopwatch.start();
          })
          .width(70)
          .height(40)

        Button('暂停')
          .backgroundColor('#FF7500')
          .onClick(() => {
            this.stopwatch.pause();
          })
          .width(70)
          .height(40)

        Button('单圈')
          .backgroundColor('#34C759')
          .onClick(() => {
            this.stopwatch.lap()
            this.laps = this.stopwatch.getAllLaps();
          })
          .width(70)
          .height(40)

        Button('重置')
          .backgroundColor('#FF3B30')
          .onClick(() => {
            this.stopwatch.reset();
            this.laps = [];
            this.currentTime = '00:00:00.000';
          })
          .width(70)
          .height(40)
      }
      .margin({ top: 40 })

      // 单圈时间列表
      List() {
        ForEach(this.laps, (item: string) => {
          ListItem() {
            Text(item)
              .fontColor(Color.Red)
              .fontSize(16)
              .padding(10)
          }
        })
      }
      .layoutWeight(1)
      .width('100%')
      .margin({ top: 20 })
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
}

更多关于HarmonyOS 鸿蒙Next中使用 Date 实现高精度毫秒级秒表的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,使用Date实现高精度毫秒级秒表,可通过Date.now()获取当前时间戳。记录开始时间戳,结束时再次获取并计算差值,得到精确到毫秒的耗时。示例代码:

let startTime = Date.now();
// 执行操作...
let endTime = Date.now();
let elapsed = endTime - startTime; // 毫秒级耗时

注意:Date.now()基于系统时间,精度受系统限制。

在HarmonyOS Next中,使用Date类实现毫秒级秒表的核心是精确获取并计算时间差。虽然Date本身精度可达毫秒,但直接连续调用可能受系统调度影响。以下是关键实现方案:

  1. 核心计时逻辑
// 记录起始时间戳
let startTime = new Date().getTime();

// 获取当前耗时
function getElapsedTime() {
    let currentTime = new Date().getTime();
    return currentTime - startTime; // 毫秒数
}
  1. 格式化显示(将毫秒转为分:秒.毫秒格式):
function formatTime(ms) {
    let minutes = Math.floor(ms / 60000);
    let seconds = Math.floor((ms % 60000) / 1000);
    let milliseconds = ms % 1000;
    
    return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}.${milliseconds.toString().padStart(3, '0')}`;
}
  1. 实现跑步计时功能
  • 使用setIntervalrequestAnimationFrame进行界面刷新
  • 暂停功能:记录暂停时的累计时间,恢复时重新设置起始时间基准
  • 圈数记录:将每次getElapsedTime()的结果存入数组
  1. 注意事项
  • Date的精度足够跑步计时使用(误差约±10ms)
  • 避免在每次渲染时创建新的Date对象,应复用时间戳
  • 考虑使用performance.now()获取更高精度的时间戳(如果可用)

此方案能满足跑步计时的基础需求,实际开发中可结合ArkUI组件实现界面交互。

回到顶部