0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DateTimeFormatterのyyyyとYYYYの違いに注意

Posted at

DateTimeFormatterのyyyyとYYYYの違いについて

Javaで日付と時刻をフォーマットするためのクラスとしてDateTimeFormatterがあります。このクラスは、日付や時刻を文字列に変換したり、文字列から日付や時刻を解析するためのフォーマットパターンを指定できます。たとえば、"yyyy-MM-dd"のようなフォーマットを指定すると、日付を「2025-01-06」のような形式に変換できます。
(Java 8以降なら変わらないと思いますが、Java21で動作確認しました)

|  JShellへようこそ -- バージョン21.0.4
|  概要については次を入力してください: /help intro
jshell> import java.time.format.DateTimeFormatter;

jshell> import java.time.LocalDate;

jshell> LocalDate date = LocalDate.now();
date ==> 2025-01-12

jshell> var formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
formatter ==> Value(YearOfEra,4,19,EXCEEDS_PAD)'-'Value(MonthOfYear,2)'-'Value(DayOfMonth,2)

jshell> date.format(formatter);
$7 ==> "2025-01-12"

このうち年を表すパターン文字列についてはドキュメント

 Symbol  Meaning                     Presentation      Examples
 ------  -------                     ------------      -------
 y       year-of-era                 year              2004; 04
 Y       week-based-year             year              1996; 96

と2つありましたので、この違いを調べてみました。

yyyyとYYYYの違い

それぞれの特徴を以下にまとめます。

yyyy: 年(Year-of-era)

  • yyyyはカレンダー年(通常の年)を表します。
  • 年の始まりは1月1日で、年末は12月31日です。
  • 例:2025-01-01yyyyで「2025」となります。

YYYY: 週基準の年(Week-based-year)

YYYYはISO週番号に基づく年を表します。

具体的にどういうことかというと、

The ISO 8601 definition for week 01 is the week with the first Thursday of the Gregorian year (i.e., of January) in it.

とのことで、「最初の木曜日を含む週」がその年の最初の週となります。

つまり、以下のようになります。

jshell> var formatter = DateTimeFormatter.ofPattern("YYYY-MM-dd");
formatter ==> Localized(WeekBasedYear,4,19,EXCEEDS_PAD)'-'Value ... r,2)'-'Value(DayOfMonth,2)

jshell> var date = LocalDate.parse("2024-12-31") ;
date ==> 2024-12-31

jshell> date.format(formatter);
$8 ==> "2025-12-31"

2024-12-31YYYY-MM-ddで文字列にフォーマットすると2025-12-31になってしまいました。

202412.png

これは2024-12-31の週の木曜日は1/2で2025年であるためです。

uuuu について

あまり使わないと思いますが、DateTimeFormatter の書式指定子には uuuu もあります。

 Symbol  Meaning                     Presentation      Examples
 u       year                        year              2004; 04

この指定子は y(year-of-era)とよく似ていますが、いくつかの違いがあります。

  • uuuu:
    • ISOベースのカレンダーシステムで使用される「年」をそのまま表します。
    • 負の値もそのまま扱い、西暦0年や負の年も表現できます。

具体的には以下のようになります。

jshell> var date = LocalDate.of(-44, 3, 15);
date ==> -0044-03-15

jshell> var formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
formatter ==> Value(YearOfEra,4,19,EXCEEDS_PAD)'-'Value(MonthOfYear,2)'-'Value(DayOfMonth,2)

jshell> date.format(formatter);
$13 ==> "0045-03-15"

jshell> var formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd");
formatter ==> Value(Year,4,19,EXCEEDS_PAD)'-'Value(MonthOfYear,2)'-'Value(DayOfMonth,2)

jshell> date.format(formatter);
$15 ==> "-0044-03-15"

紀元前44年を扱っているつもりなのですが、yyyyだと紀元45年になってしまいました。uuuuだと紀元前44年になっています。

まとめ

ドキュメントのExamples

 Symbol  Meaning                     Presentation      Examples
 ------  -------                     ------------      -------
 y       year-of-era                 year              2004; 04
 Y       week-based-year             year              1996; 96

だと一見どちらでも良さそうです。

また、例えば、Pythonだと

Python 3.12.7 (main, Oct 30 2024, 03:17:17) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import datetime
>>> date = datetime(2024, 12, 31)
>>> date.strftime("%Y-%m-%d")
'2024-12-31'

のようになり、年のフォーマットにはYを使います。
そのため何気なくYYYYを使ってしまいそうです。

しかし、week-based-yearも必要な人はどこかにいるのだと思いますが、基本的にDateTimeFormatterでYYYYを使っていたらバグの可能性が高いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?