Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Time::Pieceを使って日付の計算をしようとしてハマった話をします

More than 1 year has passed since last update.

こんばんは、Magnoliaです。

この記事はPerl Advent Calendar 2018の16日目の記事です。昨日、15日目は(予定では…)@karupaneruraさんの「ISUCON8予選問題においてPerl実装で25万点を突破する方法」でした。

さて、Qiitaに投稿するのがすっかりPerl Advent Calendarの時だけになった気がしますが…最近Perlを書く機会もすっかり無くなり、先日珍しく30分枠という長い枠で登壇しましたが、コード例はRubyで書いています。

「設計Night2018 powered by Classi」で登壇してきました - Magnolia Tech

しかし、実は最初Perlで書こうとしたのですが、ちょっと想定と違った結果になったので、結局Rubyで書き直しました、今日はその話をします。

Time::Pieceモジュール

Perlの日付処理モジュールといえばコアモジュールにTime::Pieceが用意されています。少し古い話ですが、Perl 5.10からコアモジュール入りしていて、それ以前は日付関連のモジュールはかなり混沌としていたようです。その辺りの事情は以下の記事に詳しく書かれています。

第15回 DateTime:APIの標準化をめざして:モダンPerlの世界へようこそ|gihyo.jp … 技術評論社

Time::Secondsモジュールによる日付の計算

Time::Pieceには、Time::Secondsというモジュールが同梱されていて、こちらを使うと日付の計算ができるようになります(1年後とか、1ヶ月後とか)。

use strict;
use warnings;

use Time::Piece;
use Time::Seconds;

my $t = Time::Piece->strptime('2018-01-01', '%Y-%m-%d');

my $t1 = $t + ONE_DAY;
my $t2 = $t + ONE_MONTH;
my $t3 = $t + ONE_YEAR;

print $t . "\n";
print $t1 . "\n";
print $t2 . "\n";
print $t3 . "\n";

これを実行すると…

$ perl time.pl 
Mon Jan  1 00:00:00 2018
Tue Jan  2 00:00:00 2018
Wed Jan 31 10:29:04 2018
Tue Jan  1 05:48:50 2019

年で演算すると時刻も…進んでいる??月は2月になってなくて一ヶ月進んでない??

まぁ、ドキュメントにはちゃんと書かれているんですけどね…

The methods make the assumption that there are 24 hours in a day, 7 days in a week, 365.24225 days in a year and 12 months in a year. (from The Calendar FAQ at http://www.tondering.dk/claus/calendar.html)

つまり、1年を365.24225日として計算しています…月あたりの日数は考慮していない(12等分しかしていない)ということなんですが…

4年経つと、うるう年が考慮されて丁度きれいになる…という訳だけど、ユースケース的に日付の計算をしているはずが、時刻が進むとか、月の日数に合わせた計算になっていないとか、全然直感的じゃないですよね…っていうか、普通にうるう年の日単位の計算をしてほしい…という訳で、日付の計算なのに、時刻が変わったり、月がきれいに揃わないというところにハマってしまった、という話でした。いや、ドキュメント読めばいいけど、でもユースケースと合わないと…思う。

ちなみにRubyのDateモジュールは時刻を一緒に扱わないので、そのような心配は無いです。

でも、年齢の到達日を計算する時はそれでもハマります…その辺りは冒頭で紹介したスライドをぜひ読んでみてください。

その他のハマりどころとして、3年前の「はてなデベロッパーアドンベントカレンダー 2015」にもこんな記事が有ります。

Perl の Time::Piece 利用上の注意点 - Hatena Developer Blog

というわけで、ちょっとしたTime::Pieceモジュールのちょっとしたハマりどころの紹介でした。

明日は、Morichanさんによる「Perlとクラス図の対応付け」という話です、お楽しみに!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away