各言語でスニペットのまとめエントリ第2段は日時計算です。日時データは表現方法が様々なため、必要なデータ形式にデータを変換するのが覚えれなくてイライラしますね。そこで以下の3つの表現を相互に変換するスニペットを書きました。
- 日時オブジェクト
- フォーマットされた文字列
- unixタイムスタンプ(1970-01-01 00:00:00 UTC からの経過秒数)
python
pythonはdatetimeを使います。また日付計算はtimedeltaでオフセットを表現します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #!/usr/bin/python # -*- coding: utf-8 -*- import time from datetime import datetime, timedelta # obj, text, timestamp(time)の相互変換 format = '%Y-%m-%d %H:%M:%S' orig = datetime(2009, 8, 10, 14, 53, 30) text1 = orig.isoformat(' ') # obj => txt date1 = datetime.strptime(text1, format) # txt => obj time1 = time.mktime(date1.timetuple()) # obj => time date2 = datetime.fromtimestamp(time1) # time => obj time2 = time.mktime(time.strptime(text1, format)) # txt => time text2 = datetime.fromtimestamp(time2).isoformat(' ') # time => txt (obj経由) print orig print date2 print text2 print time2 # 現在時刻 now = datetime.now() print now # 日時計算 one_hour_later = now + timedelta(hours = 1) # 1時間後 two_days_later = now + timedelta(days = 2) # 2日後 three_weeks_later = now + timedelta(weeks = 3) # 3週間後 print one_hour_later print two_days_later print three_weeks_later |
perl
perlはDateTimeオブジェクト。DateTimeオブジェクトはかなり強力ですが、文字列フォーマットを扱えないのが残念です。ここでは日付文字列を扱うのにDateTime::Format::Strptimeを使ってみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #!/usr/bin/perl use strict; use warnings; use Perl6::Say; use DateTime; use DateTime::Format::Strptime; # obj, text, timestampの相互変換 my $format = '%Y-%m-%d %H:%M:%S'; my $parser = new DateTime::Format::Strptime(pattern => $format); my $orig = DateTime->new(year => 2009, month => 8, day => 10, hour => 14, minute => 53, second => 30); my $text1 = $orig->strftime($format); # obj => txt my $date1 = $parser->parse_datetime($text1); # txt => obj my $time1 = $date1->epoch; # obj => time my $date2 = DateTime->from_epoch(epoch => $time1); # time => obj my $time2 = $parser->parse_datetime($text1)->epoch; # txt => time (obj経由) my $text2 = DateTime->from_epoch(epoch => $time2)->strftime($format); # time => txt (obj経由) say $orig; say $date2; say $time2; say $text2; # 現在時刻 my $now = DateTime->now; say $now; # 日時計算 my $one_hour_later = $now->add(hours => 1); my $two_days_later = $now->add(days => 2); my $three_weeks_later = $now->add(weeks => 3); say $one_hour_later; say $two_days_later; say $three_weeks_later; |
php
phpでの処理の特徴は、他の言語が中心に日付オブジェクトがあるのに対して、phpでは中心に日付文字列がある事ですね。文字列に対する各種処理が豊富にそろっています。あと関係ないですが、改行付きのprintがあればもっとすっきりするのにと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #!/usr/bin/php < ?php # obj, text, timestamp(time)の相互変換 $format = 'Y-m-d H:i:s'; $orig = new DateTime('2009-08-10 14:53:30'); $text1 = $orig->format($format); # obj => txt $date1 = new DateTime($text1); # txt => obj $time1 = strtotime($date1->format($format)); # obj => time (txt経由) $date2 = new DateTime(date($format, $time1)); # time => obj (txt経由) list($y, $m, $d, $h, $mi, $s) = sscanf($text1, "%d-%d-%d %d:%d:%d"); $time2 = mktime($h, $mi, $s, $m, $d, $y); # text => time $text2 = date($format, $time2); # time => text echo $orig->format($format) . "\n"; echo $date2->format($format) . "\n"; echo $text2, "\n"; echo $time2, "\n"; # 現在時刻 $now = new DateTime(); echo $now->format($format) . "\n"; # 日時計算 $one_hour_later = clone $now; $one_hour_later->modify('+1 hour'); # '+1 hour +2 day ...' $two_days_later = clone $now; $two_days_later->modify('+2 days'); $three_weeks_later = clone $now; $three_weeks_later->modify('+3 weeks'); echo $one_hour_later->format($format) . "\n"; echo $two_days_later->format($format) . "\n"; echo $three_weeks_later->format($format) . "\n"; ?> |
as3
as3はDateオブジェクトを使用します。コンストラクタが強力でオブジェクトだろうが、文字列だろうが、タイムスタンプだろうが何でも取ります。一方で日付の計算をミリ秒単位に変換して行わないと行けないのが大変です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | package { import flash.display.*; public class DatetimeTest extends Sprite { function DatetimeTest() { // obj, text, timestamp(time)の相互変換 var orig:Date = new Date(2009, 8, 10, 14, 53, 30); var text1:String = orig.toString(); // obj => txt var date1:Date = new Date(text1); // txt => obj var time1:Number = date1.getTime(); // obj => time var date2:Date = new Date(time1); // time => obj var time2:Number = (new Date(text1)).getTime(); // txt => time (obj経由) var text2:String = (new Date(time2)).toString(); // time => txt (obj経由) log(orig); log(date2); log(text2); log(time2); // 現在時刻 var now:Date = new Date(); log(now); // 日時計算 var one_hour_later:Date = new Date(now); one_hour_later.setTime(one_hour_later.getTime() + 60*60*1000); // 1時間後 var two_days_later:Date = new Date(now); two_days_later.setTime(two_days_later.getTime() + 2*24*60*60*1000); // 2日後 var three_weeks_later:Date = new Date(now); three_weeks_later.setTime(three_weeks_later.getTime() + 3*7*24*60*60*1000); // 3週間後 log(one_hour_later); log(two_days_later); log(three_weeks_later); } } } |
javascript
as3とjavascriptがこんなに似ているとは思いませんでした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | < !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>datetime test</title>
<script type="text/javascript" src="jquery-1.3.2.js"></script>
<script type="text/javascript">
$(
function() {
// obj, text, timestampの相互変換
var orig = new Date(2009, 8, 10, 14, 53, 30);
var text1 = orig.toString(); // obj => txt
var date1 = new Date(text1); // txt => obj
var time1 = date1.getTime(); // obj => time
var date2 = new Date(time1); // time => obj
var time2 = (new Date(text1)).getTime(); // txt => time (obj経由)
var text2 = (new Date(time2)).toString(); // time => txt (obj経由)
alert(text1);
alert(date2);
alert(text2);
alert(time2);
// 現在時刻
var now = new Date();
alert(now);
// 日時計算
var one_hour_later = new Date(now);
one_hour_later.setTime(one_hour_later.getTime() + 60*60*1000); // 1時間後
var two_days_later = new Date(now);
two_days_later.setTime(two_days_later.getTime() + 2*24*60*60*1000); // 2日後
var three_weeks_later = new Date(now);
three_weeks_later.setTime(three_weeks_later.getTime() + 3*7*24*60*60*1000); // 3週間後
alert(one_hour_later);
alert(two_days_later);
alert(three_weeks_later);
}
);
</script>
</head>
<body>
</body>
</html> |
まとめ
最近pythonを使い始めて肩入れしている気はしますが,pythonが一番綺麗です。timedeltaオブジェクトがあるのが素晴しいですね。どの言語でも、変換の中心になる形式があるので、その形式を押さえる事が重要そうですね。各言語とも特に不自由はありませんが、as3とjavascriptは日時計算が若干やりにくいので、やはりクライアントサイドは基本的にビューアとして考えるのがいいのかなと思いました。飛躍しましたか。そうですか。あとphpは一々惜しい印象。幾つかシンタックスシュガーを用意したら結構使い易くなるんじゃないかと思います。
おまけのMySQL
1 2 3 4 5 6 7 8 9 10 11 12 | mysql> SELECT NOW(); +---------------------+ | 2009-08-06 12:08:55 | +---------------------+ mysql> SELECT UNIX_TIMESTAMP(NOW()); +-----------------------+ | 1249528147 | +-----------------------+ mysql> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(NOW())); +--------------------------------------+ | 2009-08-06 12:09:31 | +--------------------------------------+ |
覚えにくいんですが、UNIX_TIMESTAMPとFROM_UNIXTIMEを使えると結構便利だと思います。





[...] pythonとperlとphpとas3とjavascriptで日時計算 « taichino.com : http://taichino.com/programming/794 [...]