Pythonの日時の扱い

追記

エポック秒からタイムゾーンのあるローカル時間の変換でハマったので雛形を作ってみました。

sample1:

from datetime import datetime, timezone, timedelta
import time

now = time.time()
JST = timezone(timedelta(hours=+9), 'JST')

loc = datetime.fromtimestamp(now, JST)
utc = datetime.fromtimestamp(now, timezone.utc)
print(loc)
2020-08-25 00:18:56.612099+09:00
print(utc)
2020-08-24 15:18:56.612099+00:00
loc.timestamp()
1598282336.612099
utc.timestamp()
1598282336.612099

sample2

from datetime import datetime
import tzlocal

unix_timestamp = float("1284101485")
local_timezone = tzlocal.get_localzone() # get pytz timezone
local_time = datetime.fromtimestamp(unix_timestamp, local_timezone)

print(local_time.strftime("%Y-%m-%d %H:%M:%S.%f%z (%Z)"))

utc_time = datetime.utcfromtimestamp(unix_timestamp)
print(utc_time.strftime("%Y-%m-%d %H:%M:%S.%f+00:00 (UTC)"))

Pythonで非常に悩ましいのは日時の記述方法の手段が多すぎてどれを使ったらよいのか迷うことです。当初は次のように使っていました。

import os, time
from datetime import datetime
os.environ['TZ'] = 'Asia/Tokyo'
time.tzset()
print(datetime.now())

これでも良かったのですが、いろいろ他者さんのコードを眺めているうちに、これだと環境によって問題が起こることがわかってきました。とくに旧型のWindowsはLocal時間をベースにしているので、問題が起こりそうなことは薄々分かっていました。なにぶん私の環境がLinuxなので問題はないのですが、コードがプラットフォームごとで異なる振る舞いをするのはあまり気持ちがいいものでもないので、一旦、Pythonの日時関係を整理してみました。ちなみにWindowsをUTCベースにするにはつぎのようにします。

reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /d 1 /t REG_DWORD /f

Pythonの日時データを扱う上で大事なことはつぎの3つです。

UNIX time: エポック秒: 1970/1/1 00:00:00
naive: TZを扱わない => timezone なし
aware: TZを扱う    => timezone あり

UNIX timeはUTCを基準として1970年のはじめから連続した数字です。それなのでUnix Timeをベースにして時間の前後を計算するのには適しています。しかし見やすいように表示となると変換が必要になります。
datetimeのnaiveとawareですが、とくに指定がなければnaiveになります。UTC時間とLOCAL時間の混同を避けるためにも、Timezoneで明示しておくのは良い考えでしょう。awareでTimezoneを扱う方法はいくつかあり、どれがよいのか調べてみました。

Pythonの日時データ型は次のとおりです。

string: 日時の文字列(扱いが少ない)
e.g)
'13:07:29'
'2019-09-21'

int: 数字
e.g)
2019, 9, 21

unixtime: int(secs) or float(secs)
e.g)
1569057147.0

datetime: datetime型
e.g)
datetime(2019, 9, 21, 6, 6, 6, 6, tzinfo=jst)

struct_time(named tuple): strptime型、名前付きタプル
e.g)
time.struct_time(tm_year=2019, tm_mon=9, tm_mday=21, tm_hour=8, tm_min=46, tm_sec=18, tm_wday=5, tm_yday=264, tm_isdst=0)

サブクラスオブジェクト呼び出すときの注意

datetimeモジュールのサブクラスの中には、他のモジュールと競合するものがあるので呼び出すときは注意が必要です。

  • time:timeモジュールと競合
  • timezone:pytzのサブクラスオブジェクトと競合
from datetime import datetime, date
from pytz import timezone
import pytz
jst = timezone('Asia/Tokyo')
datetime(2019, 9, 21, 6, 6, 6, 6, tzinfo=jst)

unixtime

Unixtimeを求めるときは、time.time()で呼び出すのが簡単だと思いますが、プラットフォームにより違いがあるらしいので次の書式が定形式になっているようです。

import calendar
from datetime import datetime
now = calendar.timegm(datetime.utcnow().utctimetuple())

datetime型のデータなので次のように日時を入力すれば、Unixtimeが求められます。

>>> calendar.timegm(datetime(2019,9,22,8,10,59).utctimetuple())
1569139859

LocaltimeでUnixtimeを求める場合です。

誤)

>>> import calendar
>>> from datetime import datetime
>>> from pytz import timezone
>>> jst = timezone('Asia/Tokyo')
>>> calendar.timegm(datetime(2019,9,22,8,10,59, tzinfo=jst).utctimetuple())
1569106319

(1569139859 – 1569106319) / 60 / 60 = 9.316666667

正)

>>> import calendar
>>> from datetime import datetime, timedelta, timezone
>>> jst = timezone(timedelta(hours=+9), 'JST')
>>> calendar.timegm(datetime(2019,9,22,8,10,59, tzinfo=jst).utctimetuple())
1569107459

(1569139859 – 1569107459) / 60 / 60 = 9

注意:datetime.astimezone()だと正確なUnixtimeが求められません。

例)

>>> import calendar
>>> from datetime import datetime, timedelta, timezone
>>> jst = timezone(timedelta(hours=+9), 'JST')
>>> datetime(2019,9,12,0,0,0,0).astimezone()
datetime.datetime(2019, 9, 12, 0, 0, tzinfo=datetime.timezone(datetime.timedelta(0, 32400), 'JST'))
>>> utc = timezone(timedelta(hours=0), 'UTC')
>>> datetime(2019,9,12,0,0,0,0).astimezone(utc)
datetime.datetime(2019, 9, 11, 15, 0, tzinfo=datetime.timezone(datetime.timedelta(0), 'UTC'))
>>> calendar.timegm(datetime(2019,9,12,0,0,0,0).astimezone(jst).utctimetuple())
1568214000
>>> calendar.timegm(datetime(2019,9,12,0,0,0,0).astimezone(utc).utctimetuple())
1568214000

1568214000 、同じ値になります。

>>> import pytz
utc.localize(datetime.utcnow())
>>> datetime.timestamp(pytz.utc.localize(datetime.utcnow()))
1569115999.410595

datetime型 => 日付型

読みやすいように日付型に日時データを変換する場合です。

>>> from datetime import datetime, timedelta, timezone
>>> jst = timezone(timedelta(hours=+9), 'JST'
>>> datetime.now(tz=jst).strftime('%Y-%m-%d %H:%M:%S%z')
'2019-09-22 09:45:17+0900'
>>> datetime.now(tz=jst).__format__('%Y-%m-%d %H:%M:%S%z')
'2019-09-22 09:45:56+0900'
>>> datetime(2019,9,21,tzinfo=jst).isoformat(sep=' ', timespec='seconds')
'2019-09-21 00:00:00+09:00'
>>> datetime.now(tz=jst).isoformat(sep=' ', timespec='seconds')
'2019-09-22 09:47:53+09:00'

loggingモジュールで使う場合

from datetime import datetime, timedelta, timezone
import logging
import time
import pytz
jst = pytz.timezone('Asia/Tokyo')
def localTime(*args):
    utc_now = datetime.utcnow() 
    local_now = utc_now.replace(tzinfo=pytz.utc).astimezone(jst)
    return local_now.timetuple()

logging.basicConfig(format="%(asctime)s %(message)s",
                        datefmt="%Y-%m-%d %H:%M:%S")
logging.Formatter.converter = localTime
logger = logging.getLogger(__name__)
logger.error("localTime")

メモ

'''
[words]
UNIX time: エポック秒: 1970/1/1 00:00:00
naive: TZを扱わない: timezone = False
aware: TZを扱う    : timezone = True
'''

'''
[data type]
string: 日時の文字列(扱いが少ない)
e.g)
'13:07:29'
'2019-09-21'

unixtime: int(secs) or flaot(secs)
e.g)
1569057147.0

datetime: datetime型
e.g)
datetime(2019, 9, 21, 6, 6, 6, 6, tzinfo=jst)

struct_time(named tuple): strptime型、名前付きタプル
e.g)
time.struct_time(tm_year=2019, tm_mon=9, tm_mday=21, tm_hour=8, tm_min=46, tm_sec=18, tm_wday=5, tm_yday=264, tm_isdst=0)
'''


#####################################
#          time module              #
#####################################

time.asctime([t])
'''
e.g)
>>> import time
>>> time.asctime()
'Sat Sep 21 17:44:07 2019'

   'Sun Jun 20 23:21:05 1993' といった書式の文字列に変換します。
   t が与えられていない場合には、localtime() が返す現在の時刻が使われます。
   asctime() はロケール情報を使いません。
'''

time.ctime([secs])
'''
e.g)
>>> time.ctime()
'Sat Sep 21 17:45:21 2019'

   エポックからの経過秒数で表現された時刻を、ローカルの時刻を表現する文字列に変換します。
   secs を指定しないか None を指定した場合、time() が返す値を現在の時刻として使用します。
   ctime(secs) は asctime(localtime(secs)) と等価です。ローカル情報は ctime() には使用されません。
'''

time.gmtime([secs])
'''
e.g)

>>> time.gmtime()
time.struct_time(tm_year=2019, tm_mon=9, tm_mday=21, tm_hour=8, tm_min=46, tm_sec=18, tm_wday=5, tm_yday=264, tm_isdst=0)

   エポックからの経過時間で表現された時刻を、UTC で struct_time に変換します。
   このとき dst フラグは常にゼロとして扱われます。secs を指定しないか None を指定した場合、
   time() が返す値を現在の時刻として使用します。秒の端数は無視されます。
   struct_time オブジェクトについては前述の説明を参照してください。
   calendar.timegm() はこの関数と逆の変換を行います。
'''

time.localtime([secs])
'''
e.g)
>>> time.localtime()
time.struct_time(tm_year=2019, tm_mon=9, tm_mday=21, tm_hour=17, tm_min=46, tm_sec=49, tm_wday=5, tm_yday=264, tm_isdst=0)

   gmtime() に似ていますが、ローカル時間に変換します。secs を指定しないか None を指定した場合、
   time() が返す値を現在の時刻として使用します。DST が適用されている場合は dst フラグには 1 が設定されます。
'''

time.mktime(t)
'''
e.g)
>>> now = datetime.datetime.now()
>>> print(now)
2019-09-21 18:12:27.703640
>>> print(now.timetuple())
time.struct_time(tm_year=2019, tm_mon=9, tm_mday=21, tm_hour=18, tm_min=12, tm_sec=27, tm_wday=5, tm_yday=264, tm_isdst=-1)
>>> time.mktime(now.timetuple())
1569057147.0

   localtime() の逆を行う関数です。引数は struct_time か 9 個の要素すべての値を持つ完全なタプル
   (dst フラグも必要です; 時刻に DST が適用されるか不明の場合は -1 を使用してください) で、
   UTC ではなく ローカル 時間を指定します。戻り値は time() との互換性のために浮動小数点数になります。
   入力した値を正しい時刻として表現できない場合、例外 OverflowError または ValueError が送出されます 
   (どちらが送出されるかは、無効な値を受け取ったのが Python と下層の C ライブラリのどちらなのかによって決まります)。
   この関数で時刻を生成できる最も古い日付はプラットフォームに依存します。
'''


time.strftime(format[, t])
'''
e.g)
>>> time.strftime('%Y-%m-%d %H:%M:%S', (2019, 9, 21, 6, 6, 6, 6, 6, 6))
'2019-09-21 06:06:06'
>>> time.strftime('%Y-%m-%d %H:%M:%S', datetime.now().timetuple())
'2019-09-22 00:45:16'

   gmtime() や localtime() が返す時刻値タプルまたは struct_time を、format で指定した文字列形式に変換します。
   t が与えられていない場合、localtime() が返す値を現在の時刻として使用します。format は文字列でなくてはなりません。
   t のいずれかのフィールドが許容範囲外の数値であった場合、ValueError を送出します。
'''

time.strptime(string[, format])
'''
e.g)
>>> time.strptime('2019-09-21 06:06:06', '%Y-%m-%d %H:%M:%S')
time.struct_time(tm_year=2019, tm_mon=9, tm_mday=21, tm_hour=6, tm_min=6, tm_sec=6, tm_wday=5, tm_yday=264, tm_isdst=-1)

   時刻を表現する文字列を書式に従って解釈します。返される値は gmtime() や localtime() が返すような struct_time です。
'''

time.time() :: float(t)
'''
e.g)
>>> time.time()
1569057980.8580966

エポック からの秒数を浮動小数点数で返します。 エポックの具体的な日付とうるう秒 (leap seconds) の扱いはプラットフォーム依存です。
   Windows とほとんどの Unix システムでは、エポックは (UTC で) 1970 年 1 月 1 日 0 時 0 分 0 秒で、
   うるう秒はエポック秒の時間の勘定には入りません。 これは一般に Unix 時間 と呼ばれています。
   与えられたプラットフォームでエポックが何なのかを知るには、 time.gmtime(0) の値を見てください。
   時刻は常に浮動小数点数で返されますが、すべてのシステムが 1 秒より高い精度で時刻を提供するとは限らないので注意してください。
   この関数が返す値は通常減少していくことはありませんが、この関数を 2 回呼び出し、
   その呼び出しの間にシステムクロックの時刻を巻き戻して設定した場合には、以前の呼び出しよりも低い値が返ることがあります。
'''

time.tzset()
'''
>>> os.environ['TZ'] = 'Asia/Tokyo'
>>> time.tzset()
>>> time.ctime()
'Sat Sep 21 18:32:34 2019'
>>> os.environ['TZ'] = 'UTC'
>>> time.tzset()
>>> time.ctime()
'Sat Sep 21 09:32:59 2019'

   Reset the time conversion rules used by the library routines. The environment variable TZ specifies how this is done.
   It will also set the variables tzname (from the TZ environment variable), timezone (non-DST seconds West of UTC),
   altzone (DST seconds west of UTC) and daylight (to 0 if this timezone does not have any daylight saving time rules,
    or to nonzero if there is a time, past, present or future when daylight saving time applies).

   注釈 多くの場合、環境変数 TZ を変更すると、 tzset() を呼ばない限り localtime() のような関数の出力に影響を及ぼすため、
   値が信頼できなくなってしまいます。

'''



#####################################
#          datetime module          #
#####################################

'''
Available Types: class
datetime.date - Attributes: year, month, and day
datetime.time - Attributes: hour, minute, second, microsecond, and tzinfo
datetime.date - Attributes: year, month, day, hour, minute, second, microsecond, and tzinfo
datetime.timedelta - A duration expressing the difference between two date, time, or datetime instances to microsecond resolution.
datetime.tzinfo - An abstract base class for time zone information objects. 
datetime.timezone - A class that implements the tzinfo abstract base class as a fixed offset from the UTC.

NOTE:
Objects of these types are immutable.
Objects of the date type are always naive.

An object of type time or datetime may be naive or aware.
A datetime object d is aware if d.tzinfo is not None and d.tzinfo.utcoffset(d) does not return None.
If d.tzinfo is None, or if d.tzinfo is not None but d.tzinfo.utcoffset(d) returns None, d is naive.
A time object t is aware if t.tzinfo is not None and t.tzinfo.utcoffset(None) does not return None. Otherwise, t is naive.


Structure:
Module         Subclass object:
datetime --+-- timedelta
           |
           +-- tzinfo ----- timezone
           |
           +-- time   --+
           |            +-- datetime
           +-- date   --+
'''

#### date object ####
'''
from datetime import datetime, date
'''
datetime.date(year, month, day)
'''
e.g)
>>> datetime.date(datetime(2019, 9, 21, 10, 9, 46, 358061))
datetime.date(2019, 9, 21)

datatype: datetime

All arguments are required. Arguments must be integers in the following ranges:
MINYEAR <= year <= MAXYEAR
1 <= month <= 12
1 <= day <= 指定された月と年における日数
'''

date.today()
'''
e.g)
>>> date.today()
datetime.date(2019, 9, 21)

   現在のローカルな日付を返します。date.fromtimestamp(time.time()) と等価です
'''

date.fromtimestamp(timestamp)
'''
e.g)
>>> now = time.time()
>>> date.fromtimestamp(now)
datetime.date(2019, 9, 21)

   time.time() で返されるような POSIX タイムスタンプに対応するローカルな日付を返します。
'''

date.timetuple()
'''
e.g)
>>> date.timetuple(date.today())
time.struct_time(tm_year=2019, tm_mon=9, tm_mday=21, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=264, tm_isdst=-1)

   time.localtime() が返す形式の time.struct_time を返します。
   時間、分、および秒は 0 で、DST フラグは -1 になります。 d.timetuple() は次の値と同値です:
   time.struct_time((d.year, d.month, d.day, 0, 0, 0, d.weekday(), yday, -1)) ただし
   yday = d.toordinal() - date(d.year, 1, 1).toordinal() + 1 が 1月1日に 1 で始まる現在の年の日を表す。
'''

date.isoformat()
'''
e.g)
>>> date(2019, 9, 21).isoformat()
'2019-09-21'

   ISO 8601 形式、 'YYYY-MM-DD' の日付を表す文字列を返します。
'''

date.__str__()
'''
e.g)
>>> date(2019, 9, 21).__str__()
'2019-09-21'

   date オブジェクト d において、str(d) は d.isoformat() と等価です。
'''

date.ctime()
'''
e.g)
>>> date(2019, 9, 21).ctime()
'Sat Sep 21 00:00:00 2019'

   日付を表す文字列を、例えば date(2002, 12, 4).ctime() == 'Wed Dec 4 00:00:00 2002' のようにして返します。
   ネイティブの C 関数 ctime() (time.ctime() はこの関数を呼び出しますが、
   date.ctime() は呼び出しません) が C 標準に準拠しているプラットフォームでは、
   d.ctime() は time.ctime(time.mktime(d.timetuple())) と等価です
'''

date.strftime(format)
'''
e.g)
>>> date(2019, 9, 21).strftime('%Y-%m-%d')
'2019-09-21'

  明示的な書式文字列で制御された、日付を表現する文字列を返します。 時間、分、秒を表す書式化コードは値 0 になります。
   完全な書式化ディレクティブのリストについては strftime() と strptime() の振る舞い を参照してください。
'''

date.__format__(format)
'''
e.g)
>>> date(2019, 9, 21).__format__('%Y-%m-%d')
'2019-09-21'

   date.strftime`と等価です。これにより、 :meth:`str.format() の使用時に date の書式文字列を指定できます。
   書式化コードの完全なリストについては strftime() と strptime() の振る舞い を参照してください。
'''

#### datetime object ####

'''
   datetime オブジェクトは date オブジェクトおよび time オブジェクトの全ての情報が入っている単一のオブジェクトです。
   date オブジェクトと同様に、 datetime は現在のグレゴリオ暦が両方向に延長されているものと仮定します;
   また、 time オブジェクトと同様に, datetime は毎日が厳密に 3600*24 秒であると仮定します。
'''

datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)
'''
e.g)
>>> jst = timezone('Asia/Tokyo')
>>> datetime(2019, 9, 21, 6, 6, 6, 6, tzinfo=jst)

   The year, month and day arguments are required. tzinfo may be None, or an instance of a tzinfo subclass.
   The remaining arguments must be integers in the following ranges:
'''

datetime.today()
'''
e.g)
>>> datetime.today()
datetime.datetime(2019, 9, 21, 10, 56, 41, 267091)

   現在のローカルな datetime を返します。 tzinfo は None です。 この関数は datetime.fromtimestamp(time.time()) と等価です。
   now(), fromtimestamp() も参照してください
'''

datetime.now(tz=None)
'''
e.g)
>>> datetime.now(tz=None)
datetime.datetime(2019, 9, 21, 10, 57, 16, 74633)
>>> jst = timezone(timedelta(hours=+9), 'JST')
>>> datetime.now(tz=jst)
datetime.datetime(2019, 9, 21, 19, 58, 4, 603812, tzinfo=datetime.timezone(datetime.timedelta(seconds=32400), 'JST')

   現在のローカルな日付および時刻を返します。オプションの引数 tz が None であるか指定されていない場合、
   このメソッドは today() と同様ですが、可能ならば time.time() タイムスタンプを通じて得ることができる、
   より高い精度で時刻を提供します (例えば、プラットフォームが C 関数 gettimeofday() をサポートする場合には可能なことがあります)。
   tz が None でない場合、 tz は tzinfo のサブクラスのインスタンスでなければならず、
   現在の日付および時刻は tz のタイムゾーンに変換されます。
   この場合、結果は tz.fromutc(datetime.utcnow().replace(tzinfo=tz)) と等価になります。 today(), utcnow() も参照してください。
'''

datetime.utcnow()
'''
e.g)
>>> datetime.utcnow()
datetime.datetime(2019, 9, 21, 11, 1, 26, 644089)
>>> from pytz import utc
>>> import pytz
>>> datetime.now(pytz.utc)
datetime.datetime(2019, 9, 21, 11, 8, 11, 517935, tzinfo=<UTC>)

   tzinfo が None である現在の UTC の日付および時刻を返します。 これは now() と似ていますが、
   naive な datetime オブジェクトとして現在の UTC 日付および時刻を返します。
   aware な現在の UTC datetime は datetime.now(timezone.utc) を呼び出すことで取得できます。 now() も参照してください。
'''

datetime.fromtimestamp(timestamp, tz=None)
'''
e.g)
>>> time.time()
1569064464.2774587
>>> datetime.fromtimestamp(time.time(), tz=None)
datetime.datetime(2019, 9, 21, 11, 14, 50, 455411)
>>> datetime.fromtimestamp(time.time(), tz=jst)
datetime.datetime(2019, 9, 21, 20, 15, 9, 629853, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)

   time.time() が返すような、 POSIX タイムスタンプに対応するローカルな日付と時刻を返します。
   オプションの引数 tz が None であるか、指定されていない場合、
   タイムスタンプはプラットフォームのローカルな日付および時刻に変換され、返される datetime オブジェクトは naive なものになります。
   tz が None でない場合、 tz は tzinfo のサブクラスのインスタンスでなければならず、
   現在の日付および時刻は tz のタイムゾーンに変換されます。
   この場合、結果は tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz)) と等価になります。
'''


datetime.utcfromtimestamp(timestamp)
'''
e.g)
>>> datetime.utcfromtimestamp(time.time())
datetime.datetime(2019, 9, 21, 11, 15, 49, 533910)

   与えられた POSIX タイムスタンプに対応する UTC の datetime で、 tzinfo が None に設定されたものを返します。
   タイムスタンプがプラットフォームの C 関数 gmtime() でサポートされている範囲を超えている場合には OverflowError を、
   gmtime() が失敗した場合には OSError を送出します。 サポートされている範囲は 1970 年から 2038 年に制限されていることが多いです。
   aware な datetime オブジェクトを得るには fromtimestamp() を呼んでください:
   datetime.fromtimestamp(timestamp, timezone.utc)
   POSIX 互換プラットフォームでは、これは以下の表現と等価です:
   datetime(1970, 1, 1, tzinfo=timezone.utc) + timedelta(seconds=timestamp)
'''

Python3.7: datetime.fromisoformat(date_string)
'''
e.g)
>>> datetime.fromisoformat('2019-09-21')
datetime.datetime(2019, 9, 21, 0, 0)
>>> date.fromisoformat('2019-09-21')
datetime.date(2019, 9, 21)

   Return a datetime corresponding to a date_string in one of the formats emitted by date.isoformat() and datetime.isoformat().
   Specifically, this function supports strings in the format(s) YYYY-MM-DD[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]],
   where * can match any single character.
   ご用心 This does not support parsing arbitrary ISO 8601 strings -
   it is only intended as the inverse operation of datetime.isoformat().
   A more full-featured ISO 8601 parser, dateutil.parser.isoparse is available in the third-party package dateutil.
'''

datetime.strptime(date_string, format)
'''
e.g)
>>> from datetime import  time, datetime
>>> datetime.strptime('2019-09-21 06:06:06', '%Y-%m-%d %H:%M:%S')
datetime.datetime(2019, 9, 21, 6, 6, 6)

date_string に対応した datetime を返します。 format にしたがって構文解析されます。
   これは、 datetime(*(time.strptime(date_string, format)[0:6])) と等価です。
'''

#### instance method ####

datetime.date()
'''
e.g)
>>> from timedate import date
>>> date(2019, 09, 21)
  File "<stdin>", line 1
    date(2019, 09, 21)
                ^
SyntaxError: invalid token
>>> date(2019, 9, 21)
datetime.date(2019, 9, 21)


同じ年、月、日の date オブジェクトを返します。
'''

datetime.time()
'''
e.g)
>>> from datetime import time
>>> time(11, 7, 9)
datetime.time(11, 7, 9)

同じhour、minute、second、microsecond 及び foldを持つ time オブジェクトを返します。 tzinfo は None です。
   timetz() も参照してください。
'''


datetime.astimezone(tz=None)
'''
e.g)
>>> from datetime import datetime, timedelta, timezone
>>> datetime(2019,9,12,0,0,0,0).astimezone()
datetime.datetime(2019, 9, 12, 0, 0, tzinfo=datetime.timezone(datetime.timedelta(0), 'UTC'))
>>> jst = timezone(timedelta(hours=+9), 'JST')
>>> datetime(2019,9,12,0,0,0,0).astimezone(jst)
datetime.datetime(2019, 9, 12, 9, 0, tzinfo=datetime.timezone(datetime.timedelta(seconds=32400), 'JST')


   tz を新たに tzinfo 属性 として持つ datetime オブジェクトを返します。 日付および時刻データを調整して、
   返り値が self と同じ UTC 時刻を持ち、 tz におけるローカルな時刻を表すようにします。
   もし与えられた場合、 tz は tzinfo のサブクラスのインスタンスでなければならず、
   インスタンスの utcoffset() および dst() メソッドは None を返してはなりません。
   もし self が naive ならば、おそらくシステムのタイムゾーンで時間を表現します。
   引数無し (もしくは tz=None``の形 ) で呼び出された場合、変更先のタイムゾーンはシステムのローカルなタイムゾーンだと想定されます。
   変換後の datetime インスタンスの ``.tzinfo 属性には、
   OS から取得したゾーン名とオフセットを持つ timezone インスタンスが設定されます。
   self.tzinfo が tz の場合、 self.astimezone(tz) は self に等しくなります。
   つまり、date および time に対する調整は行われません。そうでない場合、結果はタイムゾーン tz におけるローカル時刻で、
   self と同じ UTC 時刻を表すようになります。これは、astz = dt.astimezone(tz) とした後、
   astz - astz.utcoffset() は通常 dt - dt.utcoffset() と同じ date および time を持つことを示します。
   単にタイムゾーンオブジェクト tz を datetime オブジェクト dt に追加したいだけで、
   日付や時刻データへの調整を行わないのなら、dt.replace(tzinfo=tz) を使ってください。
   単に aware な datetime オブジェクト dt からタイムゾーンオブジェクトを除去したいだけで、
   日付や時刻データの変換を行わないのなら、dt.replace(tzinfo=None) を使ってください
'''

datetime.timetuple()
'''
e.g)
>>> import time
>>> now = time.time()
>>> datetime.fromtimestamp(now)
datetime.datetime(2019, 9, 21, 12, 47, 28, 217215)
>>> datetime.fromtimestamp(now).timetuple()
time.struct_time(tm_year=2019, tm_mon=9, tm_mday=21, tm_hour=12, tm_min=47, tm_sec=28, tm_wday=5, tm_yday=264, tm_isdst=-1)

   time.localtime() が返す形式の time.struct_time を返します。
   d.timetuple() は time.struct_time((d.year, d.month, d.day, d.hour, d.minute, d.second, d.weekday(), yday, dst)) と等価です。
'''

datetime.utctimetuple()
'''
e.g)
>>> datetime.fromtimestamp(now).utctimetuple()
time.struct_time(tm_year=2019, tm_mon=9, tm_mday=21, tm_hour=12, tm_min=47, tm_sec=28, tm_wday=5, tm_yday=264, tm_isdst=0)

   datetime インスタンス d が naive の場合、このメソッドは d.timetuple() と同じであり、
   d.dst() の返す内容にかかわらず tm_isdst が 0 に強制される点だけが異なります。
   DST が UTC 時刻に影響を及ぼすことは決してありません。
   d が aware だった場合、 d は d.utcoffset() を引いて UTC 時刻に正規化され、
   その時刻が time.struct_time として返されます。 tm_isdst は 0 に強制されます。
   d.year が MINYEAR もしくは MAXYEAR であり、 UTC 時刻への調整により適切な年の範囲を越えた場合、
   OverflowError が送出される可能性があることに注意してください。
'''

datetime.timestamp()
'''
e.g)
>>> datetime.timestamp(datetime.now())
1569070325.080109

   datetime インスタンスに対応する POSIX タイムスタンプを返します。 返り値は time.time() で返される値に近い float です。
   このメソッドでは naive な datetime インスタンスはローカル時刻とし、プラットフォームの C 関数 mktime() に頼って変換を行います。
   datetime は多くのプラットフォームの mktime() より広い範囲の値をサポートしているので、遥か過去の時刻や遥か未来の時刻に対し、
   このメソッドは OverflowError を送出するかもしれません
   注釈 UTC 時刻を表す naive な datetime インスタンスから直接 POSIX タイムスタンプを取得するメソッドはありません。
   アプリケーションがその変換を使っており、システムのタイムゾーンが UTC に設定されていなかった場合、
   tzinfo=timezone.utc を引数に与えることで POSIX タイムスタンプを取得できます:
   timestamp = dt.replace(tzinfo=timezone.utc).timestamp()
   もしくは直接タイムスタンプを計算することもできます:
   timestamp = (dt - datetime(1970, 1, 1)) / timedelta(seconds=1)
'''

datetime.isoformat(sep='T', timespec='auto')
'''
e.g)
>>> datetime.now()
datetime.datetime(2019, 9, 21, 12, 53, 41, 160655)
>>> datetime.now().isoformat(sep='T', timespec='auto')
'2019-09-21T12:53:08.617515

   Return a string representing the date and time in ISO 8601 format,
   YYYY-MM-DDTHH:MM:SS.ffffff or, if microsecond is 0, YYYY-MM-DDTHH:MM:SS
'''

datetime.ctime()
'''
e.g)
>>> datetime(2019,9,21,22,0,0).ctime()
'Sat Sep 21 22:00:00 2019

   日付を表す文字列を、例えば datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec  4 20:30:40 2002' のようにして返します。
   ネイティブの C 関数 ctime() (time.ctime() はこの関数を呼び出しますが、
   datetime.ctime() は呼び出しません) が C 標準に準拠しているプラットフォームでは、
   d.ctime() は time.ctime(time.mktime(d.timetuple())) と等価です
'''

datetime.strftime(format)
'''
e.g)
>>> datetime(2019, 9, 21, 0, 0, 0).strftime('%Y-%m-%d %H:%M:%S')
'2019-09-21 00:00:00'

  明示的な書式文字列で制御された、日付および時刻を表現する文字列を返します。
   完全な書式化ディレクティブのリストについては strftime() と strptime() の振る舞い を参照してください。
'''

datetime.__format__(format)
'''
e.g)
>>> datetime(2019, 9, 21, 0, 0, 0).__format__('%Y-%m-%d %H:%M:%S')
'2019-09-21 00:00:00

   date.strftime`と等価です。これにより、 :meth:`str.format() の使用時に datetime の書式文字列を指定できます。
   書式化コードの完全なリストについては strftime() と strptime() の振る舞い を参照してください。
'''


#### time object ####

datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)
'''
e.g)
>>> datetime.now()
datetime.datetime(2019, 9, 21, 13, 7, 29, 562610)
>>> datetime.time(datetime.now())
datetime.time(13, 7, 43, 218598)

   All arguments are optional. tzinfo may be None, or an instance of a tzinfo subclass.
   The remaining arguments must be integers in the following ranges:

    0 <= hour < 24,
    0 <= minute < 60,
    0 <= second < 60,
    0 <= microsecond < 1000000,
    fold in [0, 1].
'''

Pytohn 3.7: time.fromisoformat(time_string)
'''
e.g)
>>> from datetime import time
>>> time.fromisoformat('13:7:29')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Invalid isoformat string: '13:7:29'
>>> time.fromisoformat('13:07:29')
datetime.time(13, 7, 29)

   Return a time corresponding to a time_string in one of the formats emitted by time.isoformat().
   Specifically, this function supports strings in the format(s) HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]].
   ご用心 This does not support parsing arbitrary ISO 8601 strings -
   it is only intended as the inverse operation of time.isoformat().
'''

time.replace(hour=self.hour, minute=self.minute, second=self.second, microsecond=self.microsecond, tzinfo=self.tzinfo, * fold=0)
'''
e.g)
>>> time(13, 7, 29).replace(1,1,1)
datetime.time(1, 1, 1)

   キーワード引数で指定したメンバの値を除き、同じ値をもつ time オブジェクトを返します。
   データに対する変換を行わずに aware な time オブジェクトから naive な time オブジェクトを生成するために、
   tzinfo=None を指定することもできます。
'''

time.isoformat(timespec='auto')
'''
e.g)
>>> time(13, 7, 29).isoformat(timespec='auto')
'13:07:29'

   Return a string representing the time in ISO 8601 format, HH:MM:SS.ffffff or,
   if microsecond is 0, HH:MM:SS If utcoffset() does not return None, a string is appended,
   giving the UTC offset: HH:MM:SS.ffffff+HH:MM[:SS[.ffffff]] or, if self.microsecond is 0, HH:MM:SS+HH:MM[:SS[.ffffff]].
'''

#### tzinfo object ####
'''
'''

#### timezone object ####

datetime.timezone(offset, name=None)
'''
e.g)
>>> from datetime import timezone, timedelta, datetime
>>> jst = timezone(timedelta(hours=+9), 'JST')
>>> datetime.timestamp(datetime.now())
1569072574.300513
>>> datetime.fromtimestamp(datetime.timestamp(datetime.now()), jst)
datetime.datetime(2019, 9, 21, 22, 33, 0, 853514, tzinfo=datetime.timezone(datetime.timedelta(seconds=32400), 'JST'))

   ローカル時刻と UTC の差分を表す timedelta オブジェクトを offset 引数に指定しなくてはいけません。
   これは -timedelta(hours=24) から timedelta(hours=24) までの両端を含まない範囲に収まっていなくてはなりません。
   そうでない場合 ValueError が送出されます。
'''

#####################################
#          calendar module          #
#####################################

calendar.timegm(named tuple)
'''
e.g)
>>> import calendar
>>> datetime.utcnow().utctimetuple()
time.struct_time(tm_year=2019, tm_mon=9, tm_mday=21, tm_hour=13, tm_min=20, tm_sec=19, tm_wday=5, tm_yday=264, tm_isdst=0)
>>> calendar.timegm(datetime.utcnow().utctimetuple())
1569071993

   カレンダーと直接は関係無いが、 time モジュールの gmtime() 関数が返す形式の時刻を表すタプルを引数に取り、
   1970 を基点とするエポック時刻で POSIX エンコーディングであると仮定して、対応する Unix タイムスタンプの値を返します。
   実際には、 time.gmtime() と timegm() はお互いの逆関数です。
'''


#####################################
#           pytz module             #
#####################################

'''
e.g)
>>> from pytz import timezone
>>> import pytz
>>> utc = pytz.utc
>>> utc.zone
'UTC'
>>> eastern = timezone('US/Eastern')
>>> eastern.zone
'US/Eastern'
>>> amsterdam = timezone('Europe/Amsterdam')
>>> fmt = '%Y-%m-%d %H:%M:%S %Z' 
>>> loc_dt = eastern.localize(datetime(2002, 10, 27, 6, 0, 0))
>>> print(loc_dt.strftime(fmt))
2002-10-27 06:00:00 EST
>>> ams_dt = loc_dt.astimezone(amsterdam)
>>> ams_dt.strftime(fmt)
'2002-10-27 12:00:00 CET'

Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones.
'''