像 HH: mm: ss 那样格式化持续时间

有没有一种不需要处理时区就可以在 hh: mm: ss 中格式化持续时间的好方法?

我试过了:

DateTime durationDate = DateTime.fromMillisecondsSinceEpoch(0);
String duration = DateFormat('hh:mm:ss').format(durationDate);

但我总是得到1小时多,在这种情况下,它会说 01:00:00

当我这么做的时候:

Duration(milliseconds: 0).toString();

我得到了这个: 0:00:00.000000

73499 次浏览

You can use Duration and implement this method:

String _printDuration(Duration duration) {
String twoDigits(int n) => n.toString().padLeft(2, "0");
String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60));
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
return "${twoDigits(duration.inHours)}:$twoDigitMinutes:$twoDigitSeconds";
}

Usage:

final now = Duration(seconds: 30);
print("${_printDuration(now)}");

You can start creating a format yourself, come on this one:

String sDuration = "${duration.inHours}:${duration.inMinutes.remainder(60)}:${(duration.inSeconds.remainder(60))}";

You can use this:

print('${duration.inHours.toString().padLeft(2, '0')}:
${duration.inMinutes.remainder(60).toString().padLeft(2, '0')}:
${duration.inSeconds.remainder(60).toString().padLeft(2, '0')}');

Here's another version. It's all preference at this point, but I liked that it was dry and didn't need a function declaration (the wrapping function is obviously optional) though it is definately a bit function chaining heavy.

Compact

String formatTime(double time) {
Duration duration = Duration(milliseconds: time.round());
return [duration.inHours, duration.inMinutes, duration.inSeconds].map((seg) => seg.remainder(60).toString().padLeft(2, '0')).join(':');
}

Formatted version

String timeFormatter (double time) {
Duration duration = Duration(milliseconds: time.round());


return [duration.inHours, duration.inMinutes, duration.inSeconds]
.map((seg) => seg.remainder(60).toString().padLeft(2, '0'))
.join(':');
}

The shortest, most elegant and reliable way to get HH:mm:ss from a Duration is doing:

format(Duration d) => d.toString().split('.').first.padLeft(8, "0");

Example usage:

main() {
final d1 = Duration(hours: 17, minutes: 3);
final d2 = Duration(hours: 9, minutes: 2, seconds: 26);
final d3 = Duration(milliseconds: 0);
print(format(d1)); // 17:03:00
print(format(d2)); // 09:02:26
print(format(d3)); // 00:00:00
}

Just a quick implementation.

This will display the Duration in [DD]d:[HH]h:[mm]m:[ss]s format, and will ignore the leading element if it was 0. But seconds will always present.

For example:

1d:2h:3m:4s

2h:3m:4s

3m:4s

4s

0s

  /// Returns a formatted string for the given Duration [d] to be DD:HH:mm:ss
/// and ignore if 0.
static String formatDuration(Duration d) {
var seconds = d.inSeconds;
final days = seconds~/Duration.secondsPerDay;
seconds -= days*Duration.secondsPerDay;
final hours = seconds~/Duration.secondsPerHour;
seconds -= hours*Duration.secondsPerHour;
final minutes = seconds~/Duration.secondsPerMinute;
seconds -= minutes*Duration.secondsPerMinute;


final List<String> tokens = [];
if (days != 0) {
tokens.add('${days}d');
}
if (tokens.isNotEmpty || hours != 0){
tokens.add('${hours}h');
}
if (tokens.isNotEmpty || minutes != 0) {
tokens.add('${minutes}m');
}
tokens.add('${seconds}s');


return tokens.join(':');
}

Based on @diegoveloper's answer, I made it an extension which is also extendible

extension DurationExtensions on Duration {
/// Converts the duration into a readable string
/// 05:15
String toHoursMinutes() {
String twoDigitMinutes = _toTwoDigits(this.inMinutes.remainder(60));
return "${_toTwoDigits(this.inHours)}:$twoDigitMinutes";
}


/// Converts the duration into a readable string
/// 05:15:35
String toHoursMinutesSeconds() {
String twoDigitMinutes = _toTwoDigits(this.inMinutes.remainder(60));
String twoDigitSeconds = _toTwoDigits(this.inSeconds.remainder(60));
return "${_toTwoDigits(this.inHours)}:$twoDigitMinutes:$twoDigitSeconds";
}


String _toTwoDigits(int n) {
if (n >= 10) return "$n";
return "0$n";
}
}


Elaborating on other answers, here is an implementation that also formats days:

extension DurationFormatter on Duration {
/// Returns a day, hour, minute, second string representation of this `Duration`.
///
///
/// Returns a string with days, hours, minutes, and seconds in the
/// following format: `dd:HH:MM:SS`. For example,
///
///   var d = new Duration(days:19, hours:22, minutes:33);
///    d.dayHourMinuteSecondFormatted();  // "19:22:33:00"
String dayHourMinuteSecondFormatted() {
this.toString();
return [
this.inDays,
this.inHours.remainder(24),
this.inMinutes.remainder(60),
this.inSeconds.remainder(60)
].map((seg) {
return seg.toString().padLeft(2, '0');
}).join(':');
}
}

Unfortunately the intl package DateFormat class does not help: it marks the format of a Duration as not implemented:

formatDuration(DateTime reference) → String
NOT YET IMPLEMENTED. [...]

Define this:

extension on Duration {
String format() => '$this'.split('.')[0].padLeft(8, '0');
}

Usage:

String time = Duration(seconds: 3661).format(); // 01:01:01
format(Duration d) => d.toString().split('.').first.padLeft(8, "0");


main() {
final d1 = Duration(hours: 17, minutes: 3);
final d2 = Duration(hours: 9, minutes: 2, seconds: 26);
final d3 = Duration(milliseconds: 0);
print(format(d1)); // 17:03:00
print(format(d2)); // 09:02:26
print(format(d3)); // 00:00:00
}

I prefer thinking of Millisecond as its own unit, rather than as a subunit of something else. In that sense, it will have values of 0-999, so you're going to want to Pad three instead of two like I have seen with other answers. Here is an implementation:

String format(Duration o) {
var mil_s = (o.inMilliseconds % 1000).toString().padLeft(3, '0');
var sec_s = (o.inSeconds % 60).toString().padLeft(2, '0');
return o.inMinutes.toString() + ' m ' + sec_s + ' s ' + mil_s + ' ms';
}

https://api.dart.dev/dart-core/Duration-class.html

In my opinion the easiest way

String get refactoredDuration{
return Duration(seconds: duration).toString().split('.')[0];
}

You can use this:

 Text(RegExp(r'((^0*[1-9]\d*:)?\d{2}:\d{2})\.\d+$')
.firstMatch("$duration") ?.group(1) ?? '$duration'),

Modified the first so when hours are in 00 it will not show.

   extension VideoTimer on Duration {
String format() {
String twoDigits(int n) => n.toString().padLeft(2, '0');
final String twoDigitMinutes = twoDigits(inMinutes.remainder(60));
final String twoDigitSeconds = twoDigits(inSeconds.remainder(60));
final hour = twoDigits(inHours);
return "${hour == '00' ? '' : hour + ':'}$twoDigitMinutes:$twoDigitSeconds";
}
}
String myDuration(Duration duration) {
var date = duration.toString().split(":");
var hrs = date[0];
var mns = date[1];
var sds = date[2].split(".")[0];
return "$hrs:$mns:$sds";
}
String _printDuration(Duration duration) {
String twoDigits(int n) => n.toString().padLeft(2, "0");
String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60));
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
return "$twoDigitMinutes:$twoDigitSeconds";

}

          Container( //duration of video
child: Text("Total Duration: " + _printDuration(_controller.value.duration).toString()+" Position: " + _printDuration(_controller.value.position).toString()),
),