Python Language
日時
サーチ…
備考
Pythonは、日付と時刻を作成、変更、解析、操作するための組み込みメソッドと外部ライブラリの両方を提供します。
文字列をタイムゾーン対応のdatetimeオブジェクトに解析する
文字列をdatetime
オブジェクトに解析するとき、Python 3.2以降では%z
形式をサポートしています。
+HHMM
または-HHMM
形式のUTCオフセット(オブジェクトがナイーブな場合は空文字列)。
import datetime
dt = datetime.datetime.strptime("2016-04-15T08:27:18-0500", "%Y-%m-%dT%H:%M:%S%z")
Pythonの他のバージョンでは、 dateutil
ような外部ライブラリを使うことができます。これは、タイムゾーン付きの文字列を解析してdatetime
オブジェクトにすることを素早く行います。
import dateutil.parser
dt = dateutil.parser.parse("2016-04-15T08:27:18-0500")
dt
変数は、次の値を持つdatetime
オブジェクトになりました。
datetime.datetime(2016, 4, 15, 8, 27, 18, tzinfo=tzoffset(None, -18000))
簡単な日付演算
日付は孤立して存在しません。あなたは、日付の間の時間の量を見つけるか、または日付が明日になるかを決定する必要があるのが一般的です。これはtimedelta
オブジェクトを使用してtimedelta
できます
import datetime
today = datetime.date.today()
print('Today:', today)
yesterday = today - datetime.timedelta(days=1)
print('Yesterday:', yesterday)
tomorrow = today + datetime.timedelta(days=1)
print('Tomorrow:', tomorrow)
print('Time between tomorrow and yesterday:', tomorrow - yesterday)
これにより、次のような結果が得られます。
Today: 2016-04-15
Yesterday: 2016-04-14
Tomorrow: 2016-04-16
Difference between tomorrow and yesterday: 2 days, 0:00:00
基本的なdatetimeオブジェクトの使用
datetimeモジュールには、日付、時刻、日付時刻の3つの主な種類のオブジェクトが含まれています。
import datetime
# Date object
today = datetime.date.today()
new_year = datetime.date(2017, 01, 01) #datetime.date(2017, 1, 1)
# Time object
noon = datetime.time(12, 0, 0) #datetime.time(12, 0)
# Current datetime
now = datetime.datetime.now()
# Datetime object
millenium_turn = datetime.datetime(2000, 1, 1, 0, 0, 0) #datetime.datetime(2000, 1, 1, 0, 0)
これらのオブジェクトの算術演算は、同じデータ型内でのみサポートされ、異なる型のインスタンスで簡単な算術演算を実行すると、TypeErrorが発生します。
# subtraction of noon from today
noon-today
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'datetime.time' and 'datetime.date'
However, it is straightforward to convert between types.
# Do this instead
print('Time since the millenium at midnight: ',
datetime.datetime(today.year, today.month, today.day) - millenium_turn)
# Or this
print('Time since the millenium at noon: ',
datetime.datetime.combine(today, noon) - millenium_turn)
日付を反復する
時には、開始日から終了日までのある範囲の日付にわたって繰り返したいと思うことがあります。あなたはdatetime
ライブラリとtimedelta
オブジェクトを使用してそれを行うことができます:
import datetime
# The size of each step in days
day_delta = datetime.timedelta(days=1)
start_date = datetime.date.today()
end_date = start_date + 7*day_delta
for i in range((end_date - start_date).days):
print(start_date + i*day_delta)
生成するもの:
2016-07-21
2016-07-22
2016-07-23
2016-07-24
2016-07-25
2016-07-26
2016-07-27
短いタイムゾーン名を持つ文字列をタイムゾーン対応のdatetimeオブジェクトに解析する
前の例のようにdateutil
ライブラリを使用してタイムゾーン対応のタイムスタンプを解析すると、指定された「短い」タイムゾーン名でタイムスタンプを解析することもできます。
一般的にあいまいな短い時間帯の名前または略語でフォーマットされた日付の場合(たとえば中部標準時、中国標準時、キューバ標準時などのCSTなど - 詳細はこちら )、標準データベースでは必ずしも入手できないタイムゾーン省略形とtzinfo
オブジェクトの間のマッピングを指定する必要があります。
from dateutil import tz
from dateutil.parser import parse
ET = tz.gettz('US/Eastern')
CT = tz.gettz('US/Central')
MT = tz.gettz('US/Mountain')
PT = tz.gettz('US/Pacific')
us_tzinfos = {'CST': CT, 'CDT': CT,
'EST': ET, 'EDT': ET,
'MST': MT, 'MDT': MT,
'PST': PT, 'PDT': PT}
dt_est = parse('2014-01-02 04:00:00 EST', tzinfos=us_tzinfos)
dt_pst = parse('2016-03-11 16:00:00 PST', tzinfos=us_tzinfos)
これを実行した後:
dt_est
# datetime.datetime(2014, 1, 2, 4, 0, tzinfo=tzfile('/usr/share/zoneinfo/US/Eastern'))
dt_pst
# datetime.datetime(2016, 3, 11, 16, 0, tzinfo=tzfile('/usr/share/zoneinfo/US/Pacific'))
この方法でpytz
タイムゾーンを使用すると、適切にローカライズされないことに注意してください。
from dateutil.parser import parse
import pytz
EST = pytz.timezone('America/New_York')
dt = parse('2014-02-03 09:17:00 EST', tzinfos={'EST': EST})
これはpytz
タイムゾーンをdatetimeに単に付加するだけです:
dt.tzinfo # Will be in Local Mean Time!
# <DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>
このメソッドを使用している場合は、解析した後、おそらく日時の素朴な部分を再localize
する必要があります。
dt_fixed = dt.tzinfo.localize(dt.replace(tzinfo=None))
dt_fixed.tzinfo # Now it's EST.
# <DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
タイムゾーンを認識する日付時刻の作成
デフォルトでは、すべてのdatetime
オブジェクトはnaiveです。タイムゾーンを認識させるには、UTCのオフセットとタイムゾーンの省略形を日時の関数として提供するtzinfo
オブジェクトを添付する必要があります。
固定オフセットタイムゾーン
Python 3.2以降では、UTCからの固定オフセットであるtimezone
場合、 datetime
モジュールはtimedelta
と(オプションの)nameパラメータを取るtzinfo
具体的な実装であるtimezone
クラスを提供します。
from datetime import datetime, timedelta, timezone
JST = timezone(timedelta(hours=+9))
dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=JST)
print(dt)
# 2015-01-01 12:00:00+09:00
print(dt.tzname())
# UTC+09:00
dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=timezone(timedelta(hours=9), 'JST'))
print(dt.tzname)
# 'JST'
3.2より前のバージョンのPythonでは、 dateutil
などのサードパーティのライブラリを使用する必要があります。 dateutil
等価クラス、提供tzoffset
(バージョン2.5.3のような)形式の引数を取り、 dateutil.tz.tzoffset(tzname, offset)
、 offset
秒単位で指定されます。
from datetime import datetime, timedelta
from dateutil import tz
JST = tz.tzoffset('JST', 9 * 3600) # 3600 seconds per hour
dt = datetime(2015, 1, 1, 12, 0, tzinfo=JST)
print(dt)
# 2015-01-01 12:00:00+09:00
print(dt.tzname)
# 'JST'
夏時間のあるゾーン
夏時間のゾーンの場合、Python標準ライブラリは標準クラスを提供しないため、サードパーティライブラリを使用する必要があります。 pytz
とdateutil
は、タイムゾーンクラスを提供する一般的なライブラリです。
静的な時間帯に加えて、 dateutil
は夏時間を使用するタイムゾーンクラスを提供します( tz
モジュールのドキュメントを参照)。 tz.gettz()
メソッドを使用してタイムゾーンオブジェクトを取得し、それをdatetime
コンストラクタに直接渡すことができます。
from datetime import datetime
from dateutil import tz
local = tz.gettz() # Local time
PT = tz.gettz('US/Pacific') # Pacific time
dt_l = datetime(2015, 1, 1, 12, tzinfo=local) # I am in EST
dt_pst = datetime(2015, 1, 1, 12, tzinfo=PT)
dt_pdt = datetime(2015, 7, 1, 12, tzinfo=PT) # DST is handled automatically
print(dt_l)
# 2015-01-01 12:00:00-05:00
print(dt_pst)
# 2015-01-01 12:00:00-08:00
print(dt_pdt)
# 2015-07-01 12:00:00-07:00
注意 :バージョン2.5.3では、 dateutil
はあいまいな日付時刻を正しく処理せず、常に後の日付にデフォルト設定されます。例えば2015-11-01 1:30 EDT-4
表すdateutil
タイムゾーンを持つオブジェクトを作成する方法はありません。これは、夏時間の移行中であるためです。
pytz
を使用する場合、すべてのエッジケースが適切に処理されますが、 pytz
タイムゾーンは、コンストラクタを介してタイムゾーンに直接接続されるべきではありません 。代わりに、 pytz
タイムゾーンをタイムゾーンのlocalize
メソッドを使用して接続する必要があります。
from datetime import datetime, timedelta
import pytz
PT = pytz.timezone('US/Pacific')
dt_pst = PT.localize(datetime(2015, 1, 1, 12))
dt_pdt = PT.localize(datetime(2015, 11, 1, 0, 30))
print(dt_pst)
# 2015-01-01 12:00:00-08:00
print(dt_pdt)
# 2015-11-01 00:30:00-07:00
pytz
対応するタイムゾーンで日時演算を実行する場合、絶対経過時間が必要な場合はUTCで計算を実行するか、結果に対してnormalize()
を呼び出す必要があります。
dt_new = dt_pdt + timedelta(hours=3) # This should be 2:30 AM PST
print(dt_new)
# 2015-11-01 03:30:00-07:00
dt_corrected = PT.normalize(dt_new)
print(dt_corrected)
# 2015-11-01 02:30:00-08:00
ファジィ日時解析(テキストからdatetimeを抽出する)
日付の一部であると認識されない文字列の構成要素が無視される「ファジー」モードのdateutil
パーサーを使用して、テキストから日付を抽出することは可能です。
from dateutil.parser import parse
dt = parse("Today is January 1, 2047 at 8:21:00AM", fuzzy=True)
print(dt)
dt
はdatetime
オブジェクトになり、 datetime.datetime(2047, 1, 1, 8, 21)
されます。
タイムゾーンの切り替え
タイムゾーンを切り替えるには、タイムゾーンを認識する日時オブジェクトが必要です。
from datetime import datetime
from dateutil import tz
utc = tz.tzutc()
local = tz.tzlocal()
utc_now = datetime.utcnow()
utc_now # Not timezone-aware.
utc_now = utc_now.replace(tzinfo=utc)
utc_now # Timezone-aware.
local_now = utc_now.astimezone(local)
local_now # Converted to local time.
最小限のライブラリで任意のISO 8601タイムスタンプを解析する
Pythonは、ISO 8601のタイムスタンプの解析を制限しています。 strptime
場合、どの形式であるかを正確に知る必要があります。複雑な問題として、 datetime
の文字列化はISO 8601のタイムスタンプで、スペースは区切り文字と6桁の小数部になります。
str(datetime.datetime(2016, 7, 22, 9, 25, 59, 555555))
# '2016-07-22 09:25:59.555555'
小数部が0の場合は小数部は出力されません
str(datetime.datetime(2016, 7, 22, 9, 25, 59, 0))
# '2016-07-22 09:25:59'
しかし、これらの2 つの形式は、 strptime
ために異なる形式を必要とします。さらに、 strptime' does not support at all parsing minute timezones that have a
。 in it, thus
2016年7月22日09:25:+ 0300 59をcan be parsed, but the standard format
2016年7月22日午前9時25分59秒を+03:00`はできません。
iso8601
と呼ばれる単一ファイルライブラリがあり、ISO 8601のタイムスタンプとそのファイルのみを正しく解析します。
分数とタイムゾーンをサポートし、 T
セパレータはすべて単一の関数でサポートされています:
import iso8601
iso8601.parse_date('2016-07-22 09:25:59')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)
iso8601.parse_date('2016-07-22 09:25:59+03:00')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<FixedOffset '+03:00' ...>)
iso8601.parse_date('2016-07-22 09:25:59Z')
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)
iso8601.parse_date('2016-07-22T09:25:59.000111+03:00')
# datetime.datetime(2016, 7, 22, 9, 25, 59, 111, tzinfo=<FixedOffset '+03:00' ...>)
timezoneが設定されていない場合、 iso8601.parse_date
デフォルトはUTCになります。デフォルトゾーンはdefault_zone
キーワード引数で変更できます。特に、これがデフォルトの代わりにNone
である場合、明示的なタイムゾーンを持たないタイムスタンプは、代わりにnaive datetimesとして返されます。
iso8601.parse_date('2016-07-22T09:25:59', default_timezone=None)
# datetime.datetime(2016, 7, 22, 9, 25, 59)
iso8601.parse_date('2016-07-22T09:25:59Z', default_timezone=None)
# datetime.datetime(2016, 7, 22, 9, 25, 59, tzinfo=<iso8601.Utc>)
タイムスタンプをdatetimeに変換する
datetime
モジュールは、POSIX timestamp
をITC datetime
オブジェクトに変換できます。
エポックは1970年1月1日の深夜です。
import time
from datetime import datetime
seconds_since_epoch=time.time() #1469182681.709
utc_date=datetime.utcfromtimestamp(seconds_since_epoch) #datetime.datetime(2016, 7, 22, 10, 18, 1, 709000)
日付から正確に月を差し引く
calendar
モジュールの使用
import calendar
from datetime import date
def monthdelta(date, delta):
m, y = (date.month+delta) % 12, date.year + ((date.month)+delta-1) // 12
if not m: m = 12
d = min(date.day, calendar.monthrange(y, m)[1])
return date.replace(day=d,month=m, year=y)
next_month = monthdelta(date.today(), 1) #datetime.date(2016, 10, 23)
dateutils
モジュールの使用
import datetime
import dateutil.relativedelta
d = datetime.datetime.strptime("2013-03-31", "%Y-%m-%d")
d2 = d - dateutil.relativedelta.relativedelta(months=1) #datetime.datetime(2013, 2, 28, 0, 0)
時間差の計算
timedelta
モジュールは時間の差を計算するのに便利です:
from datetime import datetime, timedelta
now = datetime.now()
then = datetime(2016, 5, 23) # datetime.datetime(2016, 05, 23, 0, 0, 0)
新しいdatetime
オブジェクトを作成する場合、時間の指定はオプションです。
delta = now-then
delta
はtimedelta
型timedelta
print(delta.days)
# 60
print(delta.seconds)
# 40826
日付のn日後とn日前に取得するには、次のものを使用します。
n日後:
def get_n_days_after_date(date_format="%d %B %Y", add_days=120):
date_n_days_after = datetime.datetime.now() + timedelta(days=add_days)
return date_n_days_after.strftime(date_format)
日前日:
def get_n_days_before_date(self, date_format="%d %B %Y", days_before=120):
date_n_days_ago = datetime.datetime.now() - timedelta(days=days_before)
return date_n_days_ago.strftime(date_format)
ISO 8601タイムスタンプを取得する
タイムゾーンなし、マイクロ秒
from datetime import datetime
datetime.now().isoformat()
# Out: '2016-07-31T23:08:20.886783'
タイムゾーンでは、マイクロ秒
from datetime import datetime
from dateutil.tz import tzlocal
datetime.now(tzlocal()).isoformat()
# Out: '2016-07-31T23:09:43.535074-07:00'
マイクロ秒なしのタイムゾーン
from datetime import datetime
from dateutil.tz import tzlocal
datetime.now(tzlocal()).replace(microsecond=0).isoformat()
# Out: '2016-07-31T23:10:30-07:00'
ISO 8601形式の詳細については、 ISO 8601を参照してください。