ZetCode

Dart Duration 类

最后修改于 2025 年 5 月 25 日

Dart 中的 Duration 类表示一个时间间隔,广泛用于测量时间跨度、调度任务和执行基于时间的计算。本教程将探讨 Dart 应用程序中 Duration 类的创建、操作和应用。

Duration 概述

Duration 类是 Dart 核心库的一部分,它提供了一种精确的机制来表示天、小时、分钟、秒、毫秒和微秒等单位的时间间隔。它对于计算时间差、调度事件和管理异步操作中的延迟等任务至关重要。

该类经常与 DateTime 一起使用,用于计算时间戳之间的间隔、调度未来事件或引入延迟。作为一个不可变类,Duration 确保任何修改都会创建一个新实例,从而提高基于时间的操作的安全性与可预测性。

功能 描述 示例
创建 使用不同的时间单位定义持续时间 Duration(hours: 2)
属性(Properties) 访问不同的时间分量 duration.inMinutes
算术运算 执行加、减或缩放操作 duration1 + duration2
比较 使用关系运算符比较持续时间 duration1 > duration2
格式化 将持续时间转换为可读字符串 duration.toString()
计时器 在异步操作中使用持续时间 Future.delayed(Duration(seconds: 5))

Duration 类的不可变性确保其值在创建后不会改变,加法、减法和乘法等操作会生成新实例。这种设计通过防止意外修改来提高可靠性并简化调试。Duration 的一个关键应用是异步编程,它通过 Future.delayed(Duration(...)) 促进延迟,从而实现对时间敏感型操作的精确控制。

创建 Duration

Duration 类允许开发人员使用不同的单位(如天、小时、分钟、秒、毫秒和微秒)来定义时间间隔。所有构造函数参数都是可选的,默认为零,为指定持续时间提供了灵活性。支持负值,持续时间在内部存储为微秒,最大范围为 ±263 - 1 微秒。

duration_creation.dart
void main() {

  // Different ways to create durations
  Duration hours = Duration(hours: 2);
  Duration minutes = Duration(minutes: 30);
  Duration seconds = Duration(seconds: 45);
  Duration ms = Duration(milliseconds: 500);
  Duration us = Duration(microseconds: 1000);
  
  // Combined units
  Duration complex = Duration(
    days: 1,
    hours: 3,
    minutes: 15,
    seconds: 30,
    milliseconds: 500,
    microseconds: 250
  );
  
  print('2 hours: $hours');
  print('30 minutes: $minutes');
  print('45 seconds: $seconds');
  print('500ms: $ms');
  print('1000μs: $us');
  print('Complex duration: $complex');
}

此示例说明了如何使用从小时到微秒的不同时间单位创建持续时间,并展示了结合多个单位的复杂持续时间。

$ dart run duration_creation.dart
2 hours: 2:00:00.000000
30 minutes: 0:30:00.000000
45 seconds: 0:00:45.000000
500ms: 0:00:00.500000
1000μs: 0:00:00.001000
Complex duration: 27:15:30.500250

Duration 属性

Duration 类提供了属性来访问不同单位的时间间隔,例如 inDaysinHoursinMinutesinSecondsinMillisecondsinMicroseconds。这些属性以指定的单位返回总持续时间。

由于没有直接访问单个组件(例如一天中的小时)的属性,开发人员可以使用模运算来提取特定组件。对于负持续时间,这些属性会返回负值,从而在计算中保持一致性。

duration_properties.dart
void main() {

  Duration duration = Duration(
    days: 1,
    hours: 2,
    minutes: 30,
    seconds: 45,
    milliseconds: 500,
    microseconds: 250
  );
  
  print('In days: ${duration.inDays}');
  print('In hours: ${duration.inHours}');
  print('In minutes: ${duration.inMinutes}');
  print('In seconds: ${duration.inSeconds}');
  print('In milliseconds: ${duration.inMilliseconds}');
  print('In microseconds: ${duration.inMicroseconds}');
  
  // Individual components
  print('Days component: ${duration.inDays}');
  print('Hours component: ${duration.inHours % 24}');
  print('Minutes component: ${duration.inMinutes % 60}');
  print('Seconds component: ${duration.inSeconds % 60}');
  print('Milliseconds component: ${duration.inMilliseconds % 1000}');
  print('Microseconds component: ${duration.inMicroseconds % 1000}');
}

此示例演示了如何访问持续时间属性并使用模运算提取单个组件。

$ dart run duration_properties.dart
In days: 1
In hours: 26
In minutes: 1590
In seconds: 95445
In milliseconds: 95445500
In microseconds: 95445500250
Days component: 1
Hours component: 2
Minutes component: 30
Seconds component: 45
Milliseconds component: 500
Microseconds component: 250

Duration 算术运算

Duration 类支持算术运算,如加法、减法、乘法、取反和绝对值计算。加法组合两个持续时间,减法计算它们的差值,乘法将持续时间乘以一个整数。取反会反转持续时间的符号,abs 方法返回绝对值。除法(返回 double 而非 Duration)可用于计算持续时间之间的比率。

duration_arithmetic.dart
void main() {

  Duration d1 = Duration(hours: 2, minutes: 30);
  Duration d2 = Duration(minutes: 45);
  
  // Addition
  Duration sum = d1 + d2;
  print('Sum: $sum');
  
  // Subtraction
  Duration diff = d1 - d2;
  print('Difference: $diff');
  
  // Multiplication
  Duration multiplied = d1 * 3;
  print('Multiplied: $multiplied');
  
  // Division (returns double)
  double ratio = d1.inMinutes / d2.inMinutes;
  print('Ratio: $ratio');
  
  // Negation
  Duration negative = -d1;
  print('Negative: $negative');
  
  // Absolute value
  Duration absValue = negative.abs();
  print('Absolute: $absValue');
}

此示例演示了持续时间上的算术运算,展示了加法、减法、乘法、除法、取反和绝对值计算。

$ dart run duration_arithmetic.dart
Sum: 3:15:00.000000
Difference: 1:45:00.000000
Multiplied: 7:30:00.000000
Ratio: 3.3333333333333335
Negative: -2:30:00.000000
Absolute: 2:30:00.000000

比较 Duration

Duration 类允许使用标准运算符(如 ==<><=>=)以及 compareTo 方法进行比较。compareTo 方法根据持续时间是小于、等于还是大于另一个持续时间,返回 -1、0 或 1。比较基于总微秒数,负持续时间被认为小于正持续时间,从而确保了结果的一致性和直观性。

duration_comparison.dart
void main() {

  Duration short = Duration(minutes: 5);
  Duration medium = Duration(minutes: 15);
  Duration long = Duration(hours: 1);
  
  print('short == medium: ${short == medium}');
  print('short < medium: ${short < medium}');
  print('medium > long: ${medium > long}');
  print('short <= medium: ${short <= medium}');
  print('long >= medium: ${long >= medium}');
  
  // CompareTo returns -1, 0, or 1
  print('short.compareTo(medium): ${short.compareTo(medium)}');
  print('medium.compareTo(medium): ${medium.compareTo(medium)}');
  print('long.compareTo(medium): ${long.compareTo(medium)}');
}

此示例演示了如何使用标准运算符和 compareTo 方法比较持续时间。

格式化 Duration

Duration 类通过 toString 方法支持格式化,该方法以 HH:MM:SS.microseconds 的格式输出持续时间,负持续时间带有前导减号。对于自定义格式,开发人员可以提取小时、分钟和秒等组件,并使用 padLeft 等方法来确保一致的数字位数,从而实现定制化的字符串表示。

duration_formatting.dart
void main() {

  Duration duration = Duration(
    hours: 2,
    minutes: 15,
    seconds: 30,
    milliseconds: 500,
    microseconds: 250
  );
  
  // Standard toString() format
  print('Default format: $duration');
  
  // Custom formatting
  String formatted = [
    duration.inHours,
    duration.inMinutes.remainder(60),
    duration.inSeconds.remainder(60)
  ].map((seg) => seg.toString().padLeft(2, '0')).join(':');
  
  print('Custom format: $formatted');
  
  // For negative durations
  Duration negative = -duration;
  print('Negative format: $negative');
  
  // Formatting with milliseconds
  String withMs = '${duration.inMinutes}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}.${(duration.inMilliseconds % 1000).toString().padLeft(3, '0')}';
  print('With milliseconds: $withMs');
}

此示例演示了使用默认 toString 方法和自定义格式化技术格式化持续时间。

$ dart run duration_formatting.dart
Default format: 2:15:30.500250
Custom format: 02:15:30
Negative format: -2:15:30.500250
With milliseconds: 135:30.500

使用 DateTime

Duration 类经常与 DateTime 一起使用来进行时间计算,例如使用 add 将时间戳向前移动,使用 subtract 向后移动,或者使用 difference(返回 Duration)计算两个时间戳之间的间隔。这些操作是时区感知的,默认为本地时区,可确保时间相关逻辑的准确处理。

duration_datetime.dart
void main() {

  DateTime now = DateTime.now();
  Duration offset = Duration(days: 7, hours: 3);
  
  // Adding duration to DateTime
  DateTime future = now.add(offset);
  print('Now: $now');
  print('Future: $future');
  
  // Subtracting duration from DateTime
  DateTime past = now.subtract(offset);
  print('Past: $past');
  
  // Difference between DateTimes is a Duration
  Duration diff = future.difference(past);
  print('Difference: $diff');
  
  // Time until/since specific DateTime
  DateTime event = DateTime(2025, 12, 25);
  Duration untilEvent = event.difference(now);
  print('Days until event: ${untilEvent.inDays}');
}

此示例说明了 DurationDateTime 的结合使用,用于推进、回溯和计算时间戳之间的差异。

$ dart run duration_datetime.dart
Now: 2025-05-25 14:30:45.123456
Future: 2025-06-01 17:30:45.123456
Past: 2025-05-18 11:30:45.123456
Difference: 336:00:00.000000
Days until event: 214

计时器实现

Timer 类利用 Duration 来调度任务,从而实现在指定延迟后或以固定间隔执行。这对于在 Dart 应用程序中实现周期性操作或超时特别有用。

timer_example.dart
import 'dart:async';

void main() {

  Duration interval = Duration(seconds: 1);
  int count = 0;
  
  Timer.periodic(interval, (timer) {
    count++;
    print('Tick $count');
    
    if (count >= 5) {
      timer.cancel();
      print('Timer stopped');
    }
  });
}

此示例创建了一个周期性计时器,该计时器每秒触发一次,打印一个滴答计数,直到达到五次,此时计时器将被取消。

延迟执行

Future.delayed 构造函数与 Duration 结合使用,允许开发人员暂停代码执行指定的时间。此方法非常适合模拟延迟、实现超时或协调 Dart 应用程序中的异步操作。

delay_execution.dart
Future<void> main() async {
    
  print('Starting...');
  
  await Future.delayed(Duration(seconds: 2));
  
  print('After 2 seconds');
}

此示例使用 Future.delayed 引入两秒延迟,然后打印一条消息,演示了处理异步延迟的常用模式。

测量执行时间

Stopwatch 类与 Duration 一起使用,可以精确测量代码段的执行时间。这对于性能分析、基准测试和优化 Dart 应用程序非常有价值。

measure_time.dart
void main() {

  Stopwatch stopwatch = Stopwatch()..start();
  
  // Simulate work
  int sum = 0;
  for (int i = 0; i < 100_000_000; i++) {
    sum += i;
  }
  
  stopwatch.stop();
  print('Sum: $sum');
  print('Computation took: ${stopwatch.elapsed}');
}

此示例测量使用 Stopwatch 计算总和所花费的时间,展示了其在性能分析中的实用性。

Rate Limiting 中的 Duration

Duration 类可用于在应用程序中实现速率限制,控制操作(如 API 调用或用户交互)的频率。通过强制操作之间设置最小时间间隔,开发人员可以防止过度使用并确保系统稳定性。

rate_limiting.dart
import 'dart:async';

void main() async {

  Duration rateLimit = Duration(milliseconds: 500);
  int actionCount = 0;

  Future<void> performAction() async {
    actionCount++;
    print('Action $actionCount at ${DateTime.now()}');
    await Future.delayed(rateLimit);
  }

  for (int i = 0; i < 5; i++) {
    await performAction();
  }
}

此示例实现了一个简单的速率限制器,可确保操作之间至少间隔 500 毫秒。每个操作都使用 Future.delayedDuration 进行延迟,演示了如何在 Dart 应用程序中控制操作的频率。

来源

Dart Duration 类文档
Dart 库之旅:日期和时间

Duration 类是 Dart 核心库的基石,对于管理基于时间的操作至关重要。掌握其创建、操作和格式化对于构建健壮高效的 Dart 应用程序至关重要。

作者

我的名字是 Jan Bodnar,我是一名热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。到目前为止,我已撰写了 1400 多篇文章和 8 本电子书。我在教学编程方面拥有十多年的经验。

列出 所有 Dart 教程