
# Durations

`DurationStyle` reads and writes durations as text, in the short form `10s` and in ISO-8601 `PT10S`.

## Why use it

Timeouts, intervals and cache lifetimes are durations. Configuration should say `30s`, not `30000`, and code should get a Dart `Duration`, not a number to interpret. The default conversion service calls `DurationStyle.parse` whenever a string becomes a `Duration`: for `@Value`, `getPropertyAs<Duration>` and `@ConfigurationProperties` fields. You call `DurationStyle` yourself only to parse or print durations in your own code.

Accepted forms:

- **Short form**: a whole number with an optional unit `ns`, `us`, `ms`, `s`, `m`, `h` or `d`, in any case: `500ms`, `10s`, `-2h`, `2d`.
- **ISO-8601**: `PT10S`, `PT1H30M`, `P1DT2H`, `PT0.5S`, negative as `-PT5S`. Years and months are not accepted.
- **A plain number**: milliseconds. `@DurationUnit` (from `spring_boot_dart`) changes that unit for a `@ConfigurationProperties` field.

## Example

```properties
# lib/resources/application.properties
shop.timeout=30s
shop.retry-after=PT1M30S
shop.poll=250
```

```dart
import 'package:spring_core_dart/spring_core_dart.dart';

@Service()
class Poller {
  Poller(
    @Value(r'${shop.timeout}') this.timeout, // 30 seconds
    @Value(r'${shop.retry-after}') this.retryAfter, // 1 minute 30 seconds
    @Value(r'${shop.poll}') this.poll, // 250 milliseconds
  );

  final Duration timeout;
  final Duration retryAfter;
  final Duration poll;
}
```

In code:

```dart
DurationStyle.parse('500ms'); // Duration(milliseconds: 500)
DurationStyle.parse('P1DT2H'); // Duration(days: 1, hours: 2)
DurationStyle.parse('30', unit: ChronoUnit.seconds); // 30 seconds
DurationStyle.format(const Duration(minutes: 90)); // '90m'
DurationStyle.formatIso(const Duration(minutes: 90)); // 'PT1H30M'
ChronoUnit.seconds.of(30); // Duration(seconds: 30)
```

## Members

`DurationStyle` (static methods):

| Name | Returns | Meaning |
|---|---|---|
| `parse(value, {unit = ChronoUnit.millis})` | `Duration` | Reads the short form or ISO-8601. A number without a unit is in `unit`. Throws `FormatException` otherwise. |
| `format(value)` | `String` | The short form with the largest unit that divides the value exactly; zero is `0ms`. |
| `formatIso(value)` | `String` | ISO-8601 as `java.time.Duration.toString` writes it: hours, minutes and seconds only (`PT24H` for one day). Zero is `PT0S`. |

`ChronoUnit` values: `nanos`, `micros`, `millis`, `seconds`, `minutes`, `hours`, `days`. `unit.of(amount)` gives a `Duration`.

## In Spring (Java)

```java
// Spring Boot
Duration d = DurationStyle.detectAndParse("500ms");
Duration iso = DurationStyle.detectAndParse("P1DT2H");
String text = DurationStyle.SIMPLE.print(Duration.ofMinutes(90));
String isoText = DurationStyle.ISO8601.print(Duration.ofMinutes(90));
```

Differences that matter:

- `parse` detects the form, like Spring Boot's `detectAndParse`; `format` and `formatIso` are `SIMPLE.print` and `ISO8601.print`.
- A Dart `Duration` has microsecond precision, so `ns` values are truncated to microseconds.
- `ChronoUnit` has only the units a `Duration` can hold, from nanoseconds to days; there are no months or years.
- In Spring, duration parsing belongs to Spring Boot. Here it is part of the core.

## See also

- [ConversionService](conversion-service.md)
- [DataSize](data-size.md)
- [@Value](../config/value.md)
- [@ConfigurationProperties](../config/configuration-properties.md)
