
# Durations

`DurationStyle` は、期間を短い形式 `10s` と ISO-8601 の `PT10S` の両方でテキストとして読み書きします。

## 使う理由

タイムアウト、間隔、キャッシュの有効期間は期間です。設定には `30000` ではなく `30s` と書けるべきで、コードは解釈が必要な数値ではなく Dart の `Duration` を受け取るべきです。デフォルトの変換サービスは、文字列を `Duration` にするたびに `DurationStyle.parse` を呼びます。対象は `@Value`、`getPropertyAs<Duration>`、`@ConfigurationProperties` のフィールドです。`DurationStyle` を自分で呼ぶのは、独自のコードで期間を解析または出力するときだけです。

受け付ける形式:

- **短い形式**: 整数と、省略可能な単位 `ns`、`us`、`ms`、`s`、`m`、`h`、`d`(大文字小文字は問わない)。例: `500ms`、`10s`、`-2h`、`2d`。
- **ISO-8601**: `PT10S`、`PT1H30M`、`P1DT2H`、`PT0.5S`。負の値は `-PT5S`。年と月は受け付けません。
- **単位のない数値**: ミリ秒。`@DurationUnit`(`spring_boot_dart` のアノテーション)を使うと、`@ConfigurationProperties` のフィールドでこの単位を変えられます。

## 例

```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 秒
    @Value(r'${shop.retry-after}') this.retryAfter, // 1 分 30 秒
    @Value(r'${shop.poll}') this.poll, // 250 ミリ秒
  );

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

コードでの使い方:

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

## メンバー

`DurationStyle`(静的メソッド):

| 名前 | 戻り値 | 意味 |
|---|---|---|
| `parse(value, {unit = ChronoUnit.millis})` | `Duration` | 短い形式または ISO-8601 を読む。単位のない数値は `unit`。それ以外は `FormatException`。 |
| `format(value)` | `String` | 値を割り切れる最大の単位を使った短い形式。0 は `0ms`。 |
| `formatIso(value)` | `String` | `java.time.Duration.toString` と同じ ISO-8601。時・分・秒のみ(1 日は `PT24H`)。0 は `PT0S`。 |

`ChronoUnit` の値: `nanos`、`micros`、`millis`、`seconds`、`minutes`、`hours`、`days`。`unit.of(amount)` で `Duration` を得られます。

## 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));
```

重要な違い:

- `parse` は Spring Boot の `detectAndParse` と同じく形式を自動判別します。`format` と `formatIso` は `SIMPLE.print` と `ISO8601.print` に当たります。
- Dart の `Duration` の精度はマイクロ秒なので、`ns` の値はマイクロ秒に切り捨てられます。
- `ChronoUnit` には `Duration` が保持できる単位(ナノ秒から日まで)しかありません。月と年はありません。
- Spring では期間の解析は Spring Boot の機能です。ここではコアの一部です。

## 関連項目

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