PythonとPerlとjsの日付操作のサンプルコード
PythonとPerlとJavaScriptの3つの言語で以下の日付操作をまとめます。自分用の忘備録です。
- 現在時刻/今日の時刻オブジェクトの取得
- 文字列 → 時刻オブジェクト
- 時刻オブジェクト → 文字列
- 曜日を日本語で取得
- 足し算と引き算
- 時刻オブジェクト同士の比較
- (可能なら)タイムゾーン指定で現在時刻
サンプルコードはGitHubに公開しています。
目次
検証環境
Python
import locale import datetime # 現在時刻/今日のDateTime dt_now = datetime.datetime.now() dt_today = datetime.datetime.today() # 文字列 → DateTime型 dt_nopadding = datetime.datetime.strptime('2022/2/10 1:00:00', '%Y/%m/%d %H:%M:%S') dt_padding = datetime.datetime.strptime('2022-02-10 01:00', '%Y-%m-%d %H:%M') dt_iso = datetime.datetime.fromisoformat('2022-02-10T01:00:00') # DateTime型 → 文字列 print(dt_now.strftime('%Y年%m月%d日 %H時%M分%S秒')) # 2022年02月20日 19時46分43秒 print(dt_now.isoformat()) # 2022-02-20T19:46:43.466040 # 曜日を日本語で取得 locale.setlocale(locale.LC_TIME, 'ja_JP.UTF-8') print(dt_now.strftime('%a')) # 日 # 足し算と引き算 td_10d10h10m10s = datetime.timedelta(days=10, seconds=10, minutes=10, hours=10) print(dt_now + td_10d10h10m10s) # 2022-03-03 05:56:53.466040 print(dt_now - td_10d10h10m10s) # 2022-02-10 09:36:33.466040 # 比較 print(dt_now < dt_now + td_10d10h10m10s) # True # タイムゾーン tz_jst = datetime.timezone(datetime.timedelta(hours=9)) dt_now_jst = datetime.datetime.now(tz=tz_jst) print(dt_now_jst) # 2022-02-20 19:46:43.470019+09:00
Perl
標準モジュールだけで
use 5.30.0; use strict; use warnings; use utf8; # 埋め込みの文字列リテラルがutf8の内部文字列として解釈される use Encode qw/encode_utf8/; # 日本語を含む内部文字列を標準出力できるutf8バイナリに変換する用 use Time::Piece; use Time::Seconds qw/ONE_DAY ONE_HOUR ONE_MINUTE/; # 現在時刻/今日のTime::Piece my $now = localtime; my $today = do { my $now = localtime; my $today = Time::Piece->strptime($now->ymd, "%Y-%m-%d"); localtime($today); }; # 文字列 → Time::Piece型 my $t_nopadding = Time::Piece->strptime('2022/2/10 1:00:00', '%Y/%m/%e %k:%M:%S'); my $t_padding = Time::Piece->strptime('2022-02-10 01:00', '%Y-%m-%d %H:%M'); my $t_iso = Time::Piece->strptime('2022-02-10T01:00:00', '%Y-%m-%dT%H:%M:%S'); # Time::Piece型 → 文字列 say $now->ymd('/'), ' ', $now->hms; # 2022/02/20 21:21:47 say $now->datetime; # 2022-02-20T21:21:47 say $now->strftime('%Y年%m月%d日 %H時%M分%S秒'); # 2022年02月20日 21時21分47秒 # 曜日を日本語で取得 my @week_names = qw/日 月 火 水 木 金 土/; say encode_utf8($now->wdayname(@week_names)); # 日 # 足し算と引き算 my $future = $now + ONE_DAY * 10 + ONE_HOUR * 10 + ONE_MINUTE * 10 + 10; say $future; # Thu Mar 3 07:31:57 2022 my $past = $now - ONE_DAY * 10 - ONE_HOUR * 10 - ONE_MINUTE * 10 - 10; say $past; # Thu Feb 10 11:11:37 2022 # 比較 say $past < $future ? 'True' : 'False'; # True
Perlは日本語周りの扱いが複雑で、一応コメントで補足していますが、utf-8周りの細かい話は別の記事にしようと思っています。
追記:書きました。
外部モジュールを使って
日付の演算をするときはDateTimeモジュールが便利です。
$ cpanm DateTime $ cpanm DateTime::Format::Strptime
use 5.30.0; use strict; use warnings; use utf8; # 埋め込みの文字列リテラルがutf8の内部文字列として解釈される use Encode qw/encode_utf8/; # 漢字を含む内部文字列を標準出力できるutf8バイナリに変換する用 use DateTime; use DateTime::Format::Strptime; # 現在時刻/今日のDateTime my $dt_now = DateTime->now(time_zone => 'local'); my $dt_today = DateTime->now(time_zone => 'local'); # 文字列 → DateTime型 my $strp_YmekMS = DateTime::Format::Strptime->new( pattern => '%Y/%m/%e %k:%M:%S', locale => 'ja', time_zone => 'local', ); my $dt_nopadding = $strp_YmekMS->parse_datetime('2022/2/10 1:00:00'); my $strp_YmdHM = DateTime::Format::Strptime->new( pattern => '%Y-%m-%d %H:%M', locale => 'ja', time_zone => 'local', ); my $dt_padding = $strp_YmdHM->parse_datetime('2022-02-10 01:00'); my $strp_iso = DateTime::Format::Strptime->new( pattern => '%Y-%m-%dT%H:%M:%S', locale => 'ja', time_zone => 'local', ); my $dt_iso = $strp_iso->parse_datetime('2022-02-10T01:00:00'); # DateTime型 → 文字列 say $dt_now->ymd('/'), ' ', $dt_now->hms; # 2022/02/21 00:58:23 say $dt_now->datetime; # 2022-02-21T00:58:23 say encode_utf8($dt_now->strftime('%Y年%m月%d日 %H時%M分%S秒')); # 2022年02月21日 00時58分23秒 # 曜日を日本語で取得 my $dt = DateTime->now(locale => 'ja' , time_zone => 'local'); say encode_utf8($dt->day_abbr); # 月 # 足し算と引き算 my $future = $dt_now->clone; $future->add(days => 10, hours => 10, minutes => 10, seconds => 10); say $future; # 2022-03-03T11:08:33 my $past = $dt_now->clone; $past->subtract(days => 10, hours => 10, minutes => 10, seconds => 10); say $past; # 2022-02-10T14:48:13 # 比較 say $past < $future ? 'True' : 'False'; # True # タイムゾーン my $dt_now_jst = DateTime->now(time_zone => 'Asia/Tokyo');
JavaScript
標準モジュールだけで
function copyDate(future) { return new Date(future.getTime()) } // 現在時刻/今日のDate const now = new Date() const today = (() => { const now = new Date() return new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0) })() // 文字列 → Date型 const dtNopadding = new Date('2022/2/10 1:00:00') const dtpadding = new Date('2022-02-10 01:00') const dtISO = new Date('2022-02-10T01:00:00') // Date型 → 文字列 const y = now.getFullYear() const M = now.getMonth() const d = now.getDay() const H = now.getHours() const m = now.getMinutes() const s = now.getSeconds() console.log(`${y}年${M}月${d}日 ${H}時${m}分${s}秒`) // 2022年1月0日 19時42分24秒 const yyyy = now.getFullYear().toString().padStart(4, '0') const MM = now.getMonth().toString().padStart(2, '0') const dd = now.getDay().toString().padStart(2, '0') const HH = now.getHours().toString().padStart(2, '0') const mm = now.getMinutes().toString().padStart(2, '0') const ss = now.getSeconds().toString().padStart(2, '0') console.log(`${yyyy}-${MM}-${dd}T${HH}:${mm}:${ss}`) // 2022-01-00T19:42:24 // 曜日を日本語で取得 console.log('日月火水木金土'.charAt(now.getDay())) // 日 // 足し算と引き算 const future = copyDate(now) future.setDate(future.getDate() + 10) future.setHours(future.getHours() + 10) future.setMinutes(future.getMinutes() + 10) future.setSeconds(future.getSeconds() + 10) console.log(future) // Thu Mar 03 2022 05:52:34 GMT+0900 (日本標準時) const past = copyDate(now) past.setDate(past.getDate() - 10) past.setHours(past.getHours() - 10) past.setMinutes(past.getMinutes() - 10) past.setSeconds(past.getSeconds() - 10) console.log(past) // Thu Feb 10 2022 09:32:14 GMT+0900 (日本標準時) // 比較 console.log(`${now < future}`) // true // タイムゾーン const nowJst = new Date().toLocaleString({ timeZone: 'Asia/Tokyo' })
全体的にjsのDateを扱うのは厳しいです。
外部モジュールを使って
date-fnsというモジュールを使うことでDate型を簡単に扱えるようになります。標準モジュールだけのときと比べてかなりすっきりします。
$ npm install --save date-fns
import { format, formatISO, getDay, add, sub } from 'date-fns' // 現在時刻/今日のDate型 const now = new Date() const today = (() => { const now = new Date() return new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0) })() // 文字列 → Date型 const dtNopadding = new Date('2022/2/10 1:00:00') const dtpadding = new Date('2022-02-10 01:00') const dtISO = new Date('2022-02-10T01:00:00') // Date型 → 文字列 console.log(format(now, 'y年M月d日 H時m分s秒')) // 2022年2月20日 19時43分43秒 console.log(format(now, 'yyyy年MM月dd日 HH時mm分ss秒')) // 2022年02月20日 19時43分43秒 console.log(formatISO(now)) // 2022-02-20T19:43:43+09:00 // 曜日を日本語で取得 console.log('日月火水木金土'.charAt(getDay(now))) // 日 // 足し算と引き算 const future = add(now, { days: 10, hours: 10, minutes: 10, seconds: 10 }) console.log(future) // 2022-03-02T20:53:53.284Z const past = sub(now, { days: 10, hours: 10, minutes: 10, seconds: 10 }) console.log(past) // 2022-02-10T00:33:33.284Z // 比較 console.log(`${now < future}`) // true // タイムゾーン const nowJst = new Date().toLocaleString({ timeZone: 'Asia/Tokyo' })
参考文献
- datetime --- 基本的な日付型および時間型 — Python 3.10.0b2 ドキュメント
- Pythonのdatetimeで日付や時間と文字列を変換(strftime, strptime) | note.nkmk.me
- Pythonで日付から曜日や月を文字列(日本語や英語など)で取得 | note.nkmk.me
- Python, datetime, pytzでタイムゾーンを設定・取得・変換・削除 | note.nkmk.me
- Time::Piece - Object Oriented time objects - metacpan.org
- Time::Piece - オブジェクト指向な時間オブジェクト - perldoc.jp
- Time::Piece - 日付・時刻を扱う新しい方法 - Perlゼミ|Perlの基礎をインストールからサンプルで丁寧に解説
- DateTime - A date and time object for Perl - metacpan.org
- DateTime - 日付・時刻を汎用的に扱う - Perlゼミ|Perlの基礎をインストールからサンプルで丁寧に解説
- DateTime::Format::Strptime - Parse and format strp and strf time patterns - metacpan.org
- perlめも: マルチバイと文字列の文字列操作のお話