強火で進め このページをアンテナに追加 RSSフィード

整理された情報は こちら へどうぞ。

2015年01月02日

日付フォーマット yyyy と YYYY の違い

結論

まず最初に急いでる人向けに結論を先に書いておきます。2つの違いは以下の様に成っています。

yyyy

年(西暦)を出力

YYYY

ある年における「最初の木曜日を含む週が、その年の第1週である」というルールで年(西暦)を出力。

例えば 2015/1/1 は木曜日なのでその週の日は日曜日〜土曜日まで全て2015年の第1週という解釈になり、 2014/12/28(日曜)〜2014/12/31(水曜) の時に YYYY を使うと 2015 を返します。

きっかけ

PodcastRebuild の第73回を聴いていたら日付フォーマットで yyyy ではなく、YYYY を使った為に TwitterAndroid クライアントで不具合が出たという話が出てきました。

※根本的な原因はこのルールでサーバ側が実装されていた為、 Android クライアントで正しく認証処理が行われなかったという流れになります。自分の iPhone で主に使っている Twitter クライアントの Echofon でも同様に OAuth の認証に失敗するという症状が出ていました。

この症状が Objective-C ではどうなるのか以下の様なプログラムで検証してみました。

※まぁ、 Podcast の中では Objective-C でも同様に症状が出ると話されてましたが。

    NSDateFormatter *inputDateFormatter = [[NSDateFormatter alloc] init];
    [inputDateFormatter setDateFormat:@"yyyy/MM/dd HH:mm:ss"];
    NSString *intputDateStr = @"2014/12/28 00:00:00";
    NSDate *inputDate = [inputDateFormatter dateFromString:intputDateStr];
    
    NSDateFormatter *outputDateFormatter = [[NSDateFormatter alloc] init];
    NSString *outputDateFormatterStr = @"YYYY/MM/dd HH:mm:ss";
    [outputDateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"JST"]];
    [outputDateFormatter setDateFormat:outputDateFormatterStr];
    NSString *outputDateStr = [outputDateFormatter stringFromDate:inputDate];
    NSLog(@"%@ -> %@", intputDateStr, outputDateStr);

Podcast では %G の話も出てきましたが Objective-C で G を使った場合には A.D や 西暦 などの文字列を返すという別のルールと成っているのでその辺りの検証処理は含まれていません。

プログラムの内容は 2014/12/28 00:00:00 を YYYY/MM/dd HH:mm:ss でパースするというものです。コレを実行した所、パース後のデータは 2015/12/28 00:00:00 。 Objective-C でも確かに同様の症状となる様です( Mac/iOS ともに同じ症状でした)。

因みに Objecitve-C ( NSDateFormatter ) で指定する日付フォーマットは ISO では無く、 Unicode のフォーマットが採用されています。

Data Formatting Guide: Date Formatters

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html

まぁ、 Unicode のフォーマットでも YYYY は ISO 8601 が採用されてるみたいですが。

UTS #35: Unicode LDML: Dates

http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Field_Symbol_Table

なお、 YYYY のルールはこちら。

ある年における「最初の木曜日を含む週が、その年の第1週である。」と規定されている。

※日曜日を週の始めとして処理。

ISO 8601 - Wikipedia

http://ja.wikipedia.org/wiki/ISO_8601#.E5.B9.B4.E3.81.A8.E9.80.B1.E3.81.A8.E6.9B.9C.E6.97.A5

yyyy を想定している時のテスト

自分が作ったプログラムがちゃんと yyyy の方のルールで動いているか確認する為には境界の値、水曜と木曜が1/1となる以下の2つの値をテストした時に年が次の翌年に変換されなければ良いでしょう。

  • 2013/12/31 00:00:00
  • 2014/12/31 00:00:00

※ 2014/1/1 が水曜日、 2015/1/1 が木曜日。

YYYY を想定している時のテスト

  • 2013/12/28 00:00:00
  • 2013/12/29 00:00:00

※ 2013/12/29 (日曜日)から2014年の第1週。なので 2013/12/28 は 2013 、 2013/12/29 は 2014 となれば正しく処理できています。

YYYY なんてどんな時に使うの?

YYYY はどんな時に使うの?という声が上がっていたので、こちらについても調べてみました。すると以下のサイトでヨーロッパでよく使われてるみたいだという事が判明しました。

ISO-8601 and related - SwedeTeam

http://www.swedeteam.com/iso8601/

例えば「00W09」として製造コードが記載されていれば 00W09 → 2000-W09 → 2000年の第9週目に製造されたものという表現がされるそうです。

この件とは関係ないですがこのページに記載されている MM-DD-YYYY という年月日は USA だけで使われているという話も中々興味深かったです。なんでこんな並びになっているのか、答えは「まったく理由無し。完全に非論理的」だそうですw

関連情報

If you're using YYYY in your JVM service or %G in anything, fix it now | Hacker News

https://news.ycombinator.com/item?id=8810157

Twitter skips most of 2015, locks users out of Android app | ZDNet

http://www.zdnet.com/article/twitter-skips-most-of-2015-locks-users-out-of-android-app/

あ.あ. 2015/01/04 16:34 タイトルには違いとあるが文章を読んでも具体的な違いはわかりやすくは書いていない

つまり、プログラムを読み解く出来る人は違いを読み取ることができるのだが
そうでない人は何が違うのか全然わからない。

いわゆる、わかる人にしかわからない内容だと思います。
せっかくタイトルから興味を持った人が読んでも
解らなければタダの文字の羅列!

まぁ、読む対象者を限定しているのならばいいんでしょうけどね。
ちと残念…

nakamura001nakamura001 2015/01/04 22:26 このタイトルなので今まで日付のプログラムをした事が有るプログラマー以外は読まないかな?という前提で書いていました。はてブも沢山付いたみたなのでご指摘の部分を修正しておきました。

ご指摘ありがとうございました。

投稿したコメントは管理者が承認するまで公開されません。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト

コメントを書くには、なぞなぞ認証に回答する必要があります。