Pythonで1900年以前の日付にstrftimeのような関数を使用する方法はありますか?
-
10-07-2019 - |
質問
私はこれに気付いていませんでしたが、明らかにPythonの strftime
関数は1900年以前の日付をサポートしていません:
>>> from datetime import datetime
>>> d = datetime(1899, 1, 1)
>>> d.strftime('%Y-%m-%d')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: year=1899 is before 1900; the datetime strftime() methods require year >= 1900
自分で何かを一緒にハッキングしてこれを行うことができると確信していますが、 strftime
関数には理由があると考えています(また、pre- 1900日付)。 1900年以前の日付をサポートできるようにする必要があります。 str
を使用しますが、バリエーションが多すぎます。つまり、マイクロ秒がある場合とない場合、またはタイムゾーンがある場合とない場合があります。これに対する解決策はありますか?
違いがある場合は、これを実行して、データをテキストファイルに書き込み、Oracle SQL * Loaderを使用してデータベースにロードできるようにします。
私は本質的に、Alex Martelliの答えをやった。より完全な実装を次に示します。
>>> from datetime import datetime
>>> d = datetime.now()
>>> d = d.replace(microsecond=0, tzinfo=None)
>>> str(d)
'2009-10-29 11:27:27'
唯一の違いは、 str(d)
が d.isoformat( '')
と同等であることです。
解決
isoformat はで動作します範囲の制限のないdatetime
インスタンス:
>>> import datetime
>>> x=datetime.datetime(1865, 7, 2, 9, 30, 21)
>>> x.isoformat()
'1865-07-02T09:30:21'
異なる形式の文字列が必要な場合は、 isoformat
から取得した文字列をスライス、ダイス、リミックスするのはそれほど難しくありません。これは非常に一貫しています( YYYY-MM-DDTHH :MM:SS.mmmmmm
、マイクロ秒がゼロの場合、ドットとそれに続くマイクロ秒は省略されます。
他のヒント
strftime()
が機能する正確な年の範囲もプラットフォームによって異なります。プラットフォームに関係なく、1900年以前は使用できません。
したがって、 strftime()
を使用するソリューションはありません。幸いなことに、これを「手作業で」行うのは非常に簡単です:
>>> "%02d-%02d-%02d %02d:%02d" % (d.year,d.month,d.day,d.hour,d.minute)
'1899-01-01 00:00'
mxDateTime
は任意の日付を処理できます。 Pythonの time
および datetime
モジュールは内部的にUNIXタイムスタンプを使用するため、範囲が制限されています。
In [5]: mx.DateTime.DateTime(1899)
Out[5]: <mx.DateTime.DateTime object for '1899-01-01 00:00:00.00' at 154a960>
In [6]: DateTime.DateTime(1899).Format('%Y-%m-%d')
Out[6]: 1899-01-01
これは matplotlibソース。自分で転がすための良い出発点を提供できます。
def strftime(self, dt, fmt):
fmt = self.illegal_s.sub(r"\1", fmt)
fmt = fmt.replace("%s", "s")
if dt.year > 1900:
return cbook.unicode_safe(dt.strftime(fmt))
year = dt.year
# For every non-leap year century, advance by
# 6 years to get into the 28-year repeat cycle
delta = 2000 - year
off = 6*(delta // 100 + delta // 400)
year = year + off
# Move to around the year 2000
year = year + ((2000 - year)//28)*28
timetuple = dt.timetuple()
s1 = time.strftime(fmt, (year,) + timetuple[1:])
sites1 = self._findall(s1, str(year))
s2 = time.strftime(fmt, (year+28,) + timetuple[1:])
sites2 = self._findall(s2, str(year+28))
sites = []
for site in sites1:
if site in sites2:
sites.append(site)
s = s1
syear = "%4d" % (dt.year,)
for site in sites:
s = s[:site] + syear + s[site+4:]
return cbook.unicode_safe(s)
これは「機能」ですctimeライブラリ(UTF)の。 また、2038年を超えると問題が発生する可能性があります。