Pythonの日時

スポンサーリンク
スポンサーリンク

前提

Pythonで日時データを扱う場合は、以下のように標準ライブラリをインポートしてください。

from datetime import datetime, date, timedelta

datetimeには、以下の6つのオブジェクトがあります。

date time datetime timedelta tzinfo timezone

それぞれのオブジェクトに関数があります。
例)datetime.now(現在の日時を返します)

現在日時の取得

ローカル時間

datetime.now()

from datetime import datetime

print(datetime.now())
本日の日付のみを取得する場合は、date.today()となります。

ISOフォーマットでローカル時間を取得

datetime.now().isoformat()

from datetime import datetime

print(datetime.now())
# 2020-09-03 13:21:15.119893

print(datetime.now().isoformat())
# 2020-09-03T13:21:15.120359

datetimeのtimezoneを使ってタイムゾーン指定

datetime.now(timezone.utc)

from datetime import datetime, timezone, timedelta

print(timezone.utc)
# UTC

print(datetime.now(timezone.utc))
# 2020-09-03 04:27:44.509358+00:00
timezoneは、JSTなどの指定はできず、UTCしか指定できません。

datetimeのtimezoneでタイムゾーン指定(時差を指定

timedeltaでタイムゾーンの時間の加減を作成し、その値をtimezoneに渡します。

from datetime import datetime, timedelta, timezone

tz_jst = timedelta(hours=9)
print(tz_jst)
# 9:00:00

tz_jst = timezone(timedelta(hours=9))
print(tz_jst)
# UTC+09:00

print(datetime.now(timezone(timedelta(hours=9))))
# 2020-07-13 08:47:58.787957+09:00
次の項目のようにpytzを使った方が簡単です。

pytzを使ってタイムゾーン指定(エリア指定

from datetime import datetime
from pytz import timezone

print(datetime.now(timezone('America/New_York')))
# 2020-05-17 02:14:08.276386-04:00
タイムゾーンは、投資では以下をよく使います。
'UTC' 'Europe/London' 'America/New_York' 'Asia/Tokyo'その他はWiKiを参照してください。
List of tz database time zones - Wikipedia

タイムゾーンの追加・変換

タイムゾーンの追加

タイムゾーンが設定されていない日時に対して、タイムゾーンを追加します。
これは単に追加するだけで、タイムゾーンを追加することによって日時が変わるものではありません。

タイムゾーンの追加は、replace()localize()を利用できますが、localize()を使いましょう

replace()の場合、+09:19-04:56などと挙動がおかしいようです。

localize()の場合は、サマータイムでありえない時間になる可能性があります
本ページの下部にある別項目の「サマータイムによる日時の修正(存在しない日時になる問題)」を参照してください。

from datetime import datetime, date, timedelta
from pytz import timezone

# -------------------------------------------
# 現在日時を設定
now_date = datetime.now()

print(now_date)
# 2020-09-12 14:02:06.259781
print(now_date.tzinfo)
# None

# -------------------------------------------
# 各タイムゾーンを設定
utc_timezone = timezone('UTC')
jp_timezone  = timezone('Asia/Tokyo')
ny_timezone  = timezone('America/New_York')

# -------------------------------------------
# 以下は、挙動がおかしい。
print(now_date.replace(tzinfo=utc_timezone))
# 2020-09-12 14:02:06.259781+00:00

print(now_date.replace(tzinfo=jp_timezone))
# 2020-09-12 14:02:06.259781+09:19

print(now_date.replace(tzinfo=ny_timezone))
# 2020-09-12 14:02:06.259781-04:56

# -------------------------------------------
# 以下は、正確にタイムゾーンを付与できている。
print(utc_timezone.localize(now_date))
# 2020-09-12 14:02:06.259781+00:00

print(jp_timezone.localize(now_date))
# 2020-09-12 14:02:06.259781+09:00

print(ny_timezone.localize(now_date))
# 2020-09-12 14:02:06.259781-04:00

タイムゾーンの変換

タイムゾーンを追加または変換する際に、時間を変更します

もし時間を変更せずにタイムゾーンを変換したい場合は、一旦タイムゾーンを削除してからlocalize()でタイムゾーンを追加してください。詳しくは次の項目の「タイムゾーンの削除」を参照してください。

from datetime import datetime, date, timedelta
from pytz import timezone

# -------------------------------------------
# 現在日時を設定
now_date = datetime.now()

print(now_date)
# 2020-09-12 14:02:06.259781
print(now_date.tzinfo)
# None

# -------------------------------------------
# 各タイムゾーンを設定
utc_timezone = timezone('UTC')
jp_timezone  = timezone('Asia/Tokyo')
ny_timezone  = timezone('America/New_York')

# -------------------------------------------
print(now_date.astimezone(utc_timezone))
# 2020-09-12 05:02:06.259781+00:00

print(now_date.astimezone(jp_timezone))
# 2020-09-12 14:02:06.259781+09:00

print(now_date.astimezone(ny_timezone))
# 2020-09-12 01:02:06.259781-04:00

タイムゾーンの削除

replace(tzinfo=None)でタイムゾーンを削除することが可能です。

以下の例は、タイムゾーンを削除し、その後、別のタイムゾーンに設定しています。これで時間を変えずにタイムゾーンを変更することが可能です。

jp_date = now_date.astimezone(jp_timezone)
print(jp_date)
# 2020-09-12 14:02:06.259781+09:00

jp_date = jp_date.replace(tzinfo=None)
print(jp_date)
# 2020-09-12 14:02:06.259781

print(ny_timezone.localize(jp_date))
# 2020-09-12 14:02:06.259781-04:00

サマータイムによる日時の修正(存在しない日時になる問題)

例えば2020年のニューヨークのサマータイムは、3月8日午前2時から開始され、1時間早まります。
1時間早まることによって午前2時は3時になります。
午前2時から3時までの1時間は、存在しない時間となる訳です。

localize()でタイムゾーンを追加した場合、このサマータイムの時差の存在の有無は考慮されません

localize()でタイムゾーンを追加した値を、normalize()またはastimezone()で再度変換すると正しい時間とタイムゾーンになります。

now_date = datetime(2020, 3, 8, 2, 30, 0, 0)
print(now_date)

ny_date = ny_timezone.localize(now_date)

print(ny_date)
# 2020-03-08 02:30:00-05:00

print(ny_timezone.normalize(ny_date))
# 2020-03-08 03:30:00-04:00

print(ny_date.astimezone(ny_timezone))
# 2020-03-08 03:30:00-04:00

指定した日時で日時データを作成

日付データ

datetimedateを使用します。

date(year, month, day)

from datetime import date

print(date(2020, 1, 1))
# 2020-01-01

日時データ

datetimedatetimeを使用します。

datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)

  • year, month, day 引数は必須です。
  • day:上限値は、月末は指定した年と月による
  • hour:0〜24
  • minute:0〜60
  • second:0〜60
  • microsecond:0〜1000000
  • tzinfo:タイムゾーン形式である必要がある
  • fold:1回目[0]、2回目[1]、指定された日時が何回目を指定する。サマータイムがある地域では同じ時間が存在するためである。例えばアメリカで午前2時にサマータイムが終了すると1時間戻るため午前1時になり、この午前1時〜午前2時が2回存在することになります。
from datetime import datetime, timedelta, timezone

print(datetime(2020, 1, 1))
# 2020-01-01 00:00:00

print(datetime(2020, 1, 1, 13, 15, 30))
# 2020-01-01 13:15:30

print(datetime(2020, 1, 1, 13, 15, 30, 12))
# 2020-01-01 13:15:30.000012

print(datetime(2020, 1, 1, 13, 15, 30, 12, timezone(timedelta(hours=9)))) # 2020-01-01 13:15:30.000012+09:00

日時データから値を取得

日時データから年・月・日・時・分・秒などを取得することができます。

datetime.now().date()で年月日を、datetime.now().time()で時間を取得することもできます。

曜日は、datetime.now().weekday()で取得できますが、月曜日を0、日曜日を6として、数値で返します。

from datetime import datetime

print(datetime.now())
# 2020-09-03 13:08:35.306813

# 年月日
print(datetime.now().date())
# 2020-09-03

# 時間
print(datetime.now().time())
# 13:08:35.306813

# 年
print(datetime.now().year)
# 2020

# 月
print(datetime.now().month)
# 9

# 日
print(datetime.now().day)
# 3

# 時
print(datetime.now().hour)
# 13

# 分
print(datetime.now().minute)
# 8

# 秒
print(datetime.now().second)
# 35

# 曜日
print(datetime.now().weekday())
# 3

その他の取得できる値は以下を参照してください。

datetime --- 基本的な日付型および時間型
ソースコード: Lib/datetime.py datetime モジュールは、日付や時刻を操作するためのクラスを提供しています。 日付や時刻に対する算術がサポートされている一方、実装では出力のフォーマットや操作のための効率的な属性の抽出に重点を置いています。 Aware オブジェクトと Naive オブジェクト: 日...

文字列を日時データに変換

文字列を日時データに変換する場合は、datetime.strptimeを使います。

日時データ

from datetime import datetime

tstr = "2020-04-01 12:34:56"
tdatetime = datetime.strptime(tstr, '%Y-%m-%d %H:%M:%S')

print(tdatetime)
# 2020-04-01 12:34:56

print(type(tdatetime))
# <class 'datetime.datetime'>
"2020-04-01 12:34:56"が例えば"2020/04/01 12:34:56"のように形式が異なるとエラーになります。
ミリ秒がついている場合は'%Y-%m-%d %H:%M:%S.%f'とします。

タイムゾーン付日時データ

以下の例は、Oandaのデータ形式になっています。

from datetime import datetime

tstr = "2020-04-01 12:34:56+00:00"

tdatetime = datetime.strptime(tstr, '%Y-%m-%d %H:%M:%S%z') # ミリ秒とタイムゾーン

print(tdatetime)
# 2020-04-01 12:34:56+00:00

print(type(tdatetime))
# <class 'datetime.datetime'>
Oandaの過去データ(ヒストリカルデータ)を加工する場合はPandas(データフレーム)に変換した方が扱いやすいです。

日時データを文字列に変換

日時データを文字列に変換するにはdatetime.strftimeを使います。

from datetime import datetime

tstr = "2020-04-01 12:34:56+00:00"

tdatetime = datetime.strptime(tstr, '%Y-%m-%d %H:%M:%S%z') # ミリ秒とタイムゾーン
print(tdatetime)
# 2020-04-01 12:34:56+00:00
            
print(tdatetime.strftime('%Y/%m/%d'))
# 2020-04-01 12:34:56

datetime.strptime一文字違いなので注意してください。

日時データを文字列に変換する場合、フォーマットを自由に決めることができ、また欲しい情報のみを取り出すことができます。
書式コードは以下のドキュメントを参照してください。
https://docs.python.org/ja/3.6/library/datetime.html#strftime-and-strptime-behavior

タイムスタンプの変換

日時(DITETIME)をタイプスタンプ(UNIX TIME STAMP)に変換

少し前座が長くなっていますが、datetime.timestamp()だけで変換します。

from datetime import datetime

tstr = "2020-04-01 12:34:56"
tdatetime = datetime.strptime(tstr, '%Y-%m-%d %H:%M:%S')
print(tdatetime)
# 2020-04-01 12:34:56

print(type(tdatetime))
# <class 'datetime.datetime'>

print(tdatetime.timestamp())
# 1585712096.0

タイプスタンプ(UNIX TIME STAMP)を日時(DITETIME)に変換

from datetime import datetime

print(datetime.fromtimestamp(1585712096.0))
# 2020-04-01 12:34:56
10桁のタイムスタンプの場合は上記のとおりです。
ミリ秒がある13桁のタイムスタンプではエラーになります。
ミリ秒がある13桁の場合は、1000で割ってから変換してください。

タイプスタンプ(UNIX TIME STAMP)にタイムゾーンをつけた日時(DITETIME)に変換

from pytz import timezoneを利用し、タイムゾーンを指定します。

from datetime import datetime
from pytz import timezone

print(datetime.fromtimestamp(1585712096, timezone('America/New_York')))
# 2020-03-31 23:34:56-04:00

経過時間や過去の時間の計算

timedeltaを用いて経過などを算出します。

from datetime import datetime, timedelta

now = datetime.now()
print(now)
# 2020-05-17 15:51:51.504101

# 1分後
print(now + timedelta(minutes=1))
# 2020-05-17 15:52:51.504101

# 1分前
print(now + timedelta(minutes=-1))
# 2020-05-17 15:50:51.504101

他にも以下のように指定できます。

weeks
days
hours時間
minutes
seconds
millisecondsミリ秒
microsecondsマイクロ秒

1分30秒後などの場合は、timedelta(minutes=1, seconds=30)と指定します。
年月は指定できません。次のようにします。

年月

年月の経過や過去の日付を取得するには、dateutil.relativedeltaを使用します。

from datetime import datetime
from dateutil.relativedelta import relativedelta

now = datetime.now()
print(now)
# 2020-05-17 15:58:12.532957

# 1ヶ月後
print(now + relativedelta(months=1))

# 1ヶ月前
print(now - relativedelta(months=1))

dateutil.relativedeltaでは、他にも以下を使用できます。

  1. Year
  2. Month
  3. Day
  4. Hours
  5. Minutes
  6. Seconds
  7. Microseconds

こちらも、relativedelta(hours=1, day=1)のように指定ができます。

timedeltaを使う意味がないように思えますね。。。

時間の差分

from datetime import datetime

dt1 = datetime.strptime("2020-04-01 12:00:00", '%Y-%m-%d %H:%M:%S')
dt2 = datetime.strptime("2020-04-01 12:30:00", '%Y-%m-%d %H:%M:%S')


diff = dt2 - dt1
print(diff)
# 0:30:00

print(diff.seconds)
# 1800
差分を時間形式ではなく、値を取得する際には、次の3つが利用できます。
days, seconds, microseconds分などで取得したい場合は、以下のように計算するしか方法はありません。
print(diff.seconds / 60)

営業日(翌営業日など

シストレの場合は、株式の取引所の休日と異なることがあるので注意してください。

翌営業日などは、pandasのDateOffsetにあるBusinessDayまたはBdayを利用すれば簡単に出力することができます。BdayBusinessDayのエイリアスです。

ただし、祝日は考慮されていません。

以下の例は、当日の曜日は3となっていますので木曜日になり、その2営業日後を算出います。

from datetime import date
from pandas.tseries.offsets import BusinessDay

today = date.today()
print(today, today.weekday())
# 2020-09-03 3

nextday = today + BusinessDay(2)
print(nextday)
# 2020-09-07 00:00:00

print(nextday.date())
# 2020-09-07
2営業日を加算後は日時データになってしまいますので、date()で日付形式に戻す必要があります。

アメリカの営業日の計算

pandasのCustomBusinessDayUSFederalHolidayCalendarを使います。

USFederalHolidayCalendarはpandasが用意した唯一のカレンダーになります。
そのアメリカのカレンダーをCustomBusinessDayにセットします。

from datetime import date

from pandas.tseries.offsets import CustomBusinessDay
from pandas.tseries.holiday import USFederalHolidayCalendar

today = date(2020, 9, 3)
print(today, today.weekday())
# 2020-09-03 3

cday = CustomBusinessDay(calendar=USFederalHolidayCalendar())

nextday = today + cday*2
print(nextday)
# 2020-09-08 00:00:00
n日後はBusinessDay(n)のようにカッコで指定できません。cday*nと掛け算してください。

日本の営業日の計算

日本の場合、pandasのCustomBusinessDayを使うのは同じですが、カレンダーはjpholidayを使用します。

jpholiday.year_holidays(2020)

上記のように祝日のカレンダーを取得し日付をリスト型に変換します。
jpholidayについては次の項目の祝日を参照してください。

from datetime import date

from pandas.tseries.offsets import CustomBusinessDay
import jpholiday

today = date(2020, 9, 17)
print(today, today.weekday())
# 2020-09-17 3

JapanHolidayCalendar = [val[0] for val in jpholiday.year_holidays(2020)]

cday = CustomBusinessDay(holidays=JapanHolidayCalendar)

nextday = today + cday*2
print(nextday)
# 2020-09-23 00:00:00
この例では単年しか取得していないので注意してください。

祝日

日本

jpholidayというライブラリを利用します。

import jpholiday

標準ではないのでインストールが必要になります。
例)pip install jpholiday

一覧

以下では、2020年の祝日一覧を取得します。

print(jpholiday.year_holidays(2020))

# [(datetime.date(2020, 1, 1), '元日'), (datetime.date(2020, 1, 13), '成人の日'), (datetime.date(2020, 2, 11), '建国記念の日'), (datetime.date(2020, 2, 23), '天皇誕生日'), (datetime.date(2020, 2, 24), '天皇誕生日 振替休日'), (datetime.date(2020, 3, 20), '春分の日'), (datetime.date(2020, 4, 29), '昭和の日'), (datetime.date(2020, 5, 3), '憲法記念日'), (datetime.date(2020, 5, 4), 'みどりの日'), (datetime.date(2020, 5, 5), 'こどもの日'), (datetime.date(2020, 5, 6), '憲法記念日 振替休日'), (datetime.date(2020, 7, 23), '海の日'), (datetime.date(2020, 7, 24), 'スポーツの日'), (datetime.date(2020, 8, 10), '山の日'), (datetime.date(2020, 9, 21), '敬老の日'), (datetime.date(2020, 9, 22), '秋分の日'), (datetime.date(2020, 11, 3), '文化の日'), (datetime.date(2020, 11, 23), '勤労感謝の日')]

祝日名を取得

print(jpholiday.is_holiday_name(date(2020, 1, 1)))
# 元日
datedatetimeライブラリのdateになりますのでインポートを忘れないようにしてください。

祝日か判断

if jpholiday.is_holiday(date(2020, 1, 1)) is False:
    print("NO")

祝日であるとしたい場合は、in not Falseとしてください。
タイトルとURLをコピーしました