@@ -1399,17 +1399,118 @@ head:
13991399- `BigDecimal`を`String`変換する際は`toString ()`ではなく`toPlainString ()`を利用すること
14001400 `toString ()`を利用した場合、指数表記になることがあります。
14011401
1402- ## 日付
1402+ ## 日付と時刻 (java.timeパッケージ)
14031403
1404- - 日付の文字列のフォーマットには、`SimpleDateFormat`または`DateTimeFormatter`を使う
1405- 良い例:
1404+ - 日付や時刻の扱いは`java.time`パッケージのAPIを標準とする
1405+ `java.util.Date`や`java.text.SimpleDateFormat`といった古いAPIは、スレッドセーフではなく、設計上の問題も多いため、**原則として使用を禁止**します。
1406+
1407+ - 適切な日時クラスを選択する
1408+
1409+ | 利用シーン | クラス |
1410+ | ----------------------------------------------------------------- | ------------------------------------------------------------------------ |
1411+ | 日付のみ | `LocalDate` |
1412+ | 時刻のみ | `LocalTime` |
1413+ | 日付と時刻 | `LocalDateTime` |
1414+ | タイムゾーンを考慮した日付と時刻 | `ZonedDateTime` |
1415+ | UTCからのオフセットを考慮した日付と時刻 | `OffsetDateTime` |
1416+ | 特定の日付や時刻に依存しない期間(時間量)<br> 例: 2時間30分 | `Duration` |
1417+ | 特定の日付や時刻に依存しない期間(日付ベース)<br> 例: 1年2ヶ月3日 | `Period` |
1418+ | タイムゾーン | 常に `ZoneId` を使用<br> `"Asia/Tokyo"`のような地域名で指定することを推奨 |
1419+
1420+ - 現在の日時を取得する際は、常に`Clock`クラスを依存性注入(DI)して使用することを推奨する
1421+
1422+ 良い例:
1423+
1424+ ```java
1425+ // ClockをDIで受け取る
1426+ public class MyService {
1427+ private final Clock clock;
1428+
1429+ public MyService(Clock clock) {
1430+ this . clock = clock;
1431+ }
1432+
1433+ public void doSomething() {
1434+ LocalDateTime now = LocalDateTime . now(clock);
1435+ // ...
1436+ }
1437+ }
1438+ ```
1439+
1440+ 悪い例:
1441+
1442+ ```java
1443+ // デフォルトのシステム時刻に依存
1444+ LocalDateTime now = LocalDateTime . now();
1445+ ```
1446+
1447+ - 日時のフォーマットとパースには、スレッドセーフな`DateTimeFormatter `を使用する
1448+
1449+ 良い例:
1450+
1451+ ```java
1452+ DateTimeFormatter formatter = DateTimeFormatter . ofPattern(" yyyy/MM/dd HH:mm:ss" );
1453+ LocalDateTime dateTime = LocalDateTime . parse(" 2024/10/26 13:45:00" , formatter);
1454+ String formatted = dateTime. format(formatter);
1455+ ```
1456+
1457+ - 日時の前後関係を比較する際は、`isAfter ()`, `isBefore ()`, `isEqual ()`メソッドを使用する
1458+ `<`や`> `などの比較演算子は使用不可
1459+
1460+ 良い例:
1461+
1462+ ```java
1463+ if (dateTime1 .isAfter (dateTime2 )) {
1464+ // dateTime1がdateTime2より後の場合
1465+ }
1466+ ```
1467+
1468+ - 日時の加算・減算には`plus ()`, `minus ()`メソッドを使用する
1469+ エポック秒(ミリ秒)を直接加算・減算するような計算は、うるう年やサマータイムの考慮漏れに繋がるため使用しない
1470+
1471+ - 期間の計算には`ChronoUnit`や`Duration`/`Period`クラスを使用する
1472+
1473+ 良い例:
1474+
1475+ ```java
1476+ // 2週間後を計算
1477+ LocalDate twoWeeksLater = localDate.plus (2 , ChronoUnit .WEEKS );
1478+ // 90分前を計算
1479+ LocalDateTime ninetyMinutesAgo = localDateTime. minusMinutes(90 );
1480+ ```
1481+
1482+ 悪い例:
14061483
14071484 ```java
1408- Date date = new Date ();
1409- SimpleDateFormat dateFormat = new SimpleDateFormat (" yyyy/MM/dd" );
1410- String s = dateFormat. format(date);
1485+ long oneHourInMillis = 60 * 60 * 1000 ;
1486+ long nextHour = System . currentTimeMillis() + oneHourInMillis; // タイムゾーンやサマータイムの変更に対応できない
14111487 ```
14121488
1489+ - `Duration `と`Period `を使い分ける
1490+ ナノ秒単位の精度で** 時間ベースの期間** (時、分、秒)を扱う場合は`Duration `を使用する。
1491+ 例:処理時間、タイムアウト設定、有効期限(24 時間など)
1492+
1493+ ** 日付ベースの期間** (年、月、日)を扱う場合は`Period `を使用する。
1494+ 例:契約期間(3 ヶ月)、年齢計算
1495+
1496+ `Instant `間の差を計算するには`Duration `を使用する。
1497+ `Duration.between ()`または`Instant.until ()`を利用する。
1498+
1499+ 良い例:
1500+
1501+ ```java
1502+ Instant start = Instant.now ();
1503+ // ...処理
1504+ Instant end = Instant . now();
1505+ Duration duration = Duration . between(start, end);
1506+ System.out.println ("処理時間: " + duration .toMillis () + "ミリ秒");
1507+ ```
1508+
1509+ - `ZonedDateTime `と`OffsetDateTime `を使い分ける
1510+ `ZonedDateTime `: 「東京時間」や「ニューヨーク時間」のように、** 特定のタイムゾーンルール(サマータイムを含む)を考慮する必要がある場合** に使用する。ユーザーの地域に合わせた日時を表示する際などに適する。
1511+
1512+ `OffsetDateTime `: ログのタイムスタンプやAPI 間のデータ交換など、** UTC からの固定オフセット(例: `+ 09: 00 `)のみで十分な場合** に使用する。オフセットはサマータイムのルールを保持しないため、将来の日時計算には不向きな場合がある。
1513+
14131514## 三項演算子
14141515
14151516- 入れ子の三項演算子の利用は禁止
0 commit comments