有没有办法在 Python 中对 1900 年之前的日期使用类似 strftime 的函数?

发布于 2024-08-09 05:52:45 字数 964 浏览 6 评论 0 原文

我没有意识到这一点,但显然 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< /code> 函数的存在是有原因的(而且它不支持 1900 年之前的日期也是有原因的)。我需要能够支持 1900 年之前的日期。我只使用 str,但变化太多。换句话说,它可能有也可能没有微秒,或者可能有也可能没有时区。有什么办法解决这个问题吗?

如果有影响,我这样做是为了可以将数据写入文本文件并使用 Oracle SQL*Loader 将其加载到数据库中。

我基本上最终完成了亚历克斯·马泰利的回答。下面是更完整的实现:

>>> 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(' ')

I didn't realize this, but apparently Python's strftime function doesn't support dates before 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

I'm sure I could hack together something myself to do this, but I figure the strftime function is there for a reason (and there also is a reason why it can't support pre-1900 dates). I need to be able to support dates before 1900. I'd just use str, but there's too much variation. In other words, it may or may not have microseconds or it may or may not have a timezone. Is there any solution to this?

If it makes a difference, I'm doing this so that I can write the data to a text file and load it into a database using Oracle SQL*Loader.

I essentially ended up doing Alex Martelli's answer. Here's a more complete implementation:

>>> from datetime import datetime
>>> d = datetime.now()
>>> d = d.replace(microsecond=0, tzinfo=None)
>>> str(d)
'2009-10-29 11:27:27'

The only difference is that str(d) is equivalent to d.isoformat(' ').

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

甲如呢乙后呢 2024-08-16 05:52:45

isoformat 适用于 datetime 实例没有范围限制:

>>> import datetime
>>> x=datetime.datetime(1865, 7, 2, 9, 30, 21)
>>> x.isoformat()
'1865-07-02T09:30:21'

如果您需要不同格式的字符串,那么对从 isoformat 获得的字符串进行切片、切块和重新混合并不难,这是非常一致的(< code>YYYY-MM-DDTHH:MM:SS.mmmmmm,如果微秒为零,则省略点和后面的微秒)。

isoformat works on datetime instances w/o limitation of range:

>>> import datetime
>>> x=datetime.datetime(1865, 7, 2, 9, 30, 21)
>>> x.isoformat()
'1865-07-02T09:30:21'

If you need a different-format string it's not too hard to slice, dice and remix pieces of the string you get from isoformat, which is very consistent (YYYY-MM-DDTHH:MM:SS.mmmmmm, with the dot and following microseconds omitted if microseconds are zero).

蓝天 2024-08-16 05:52:45

文档似乎对此非常清楚:

strftime() 工作的确切年份范围也因平台而异。无论何种平台,1900 年之前的年份都无法使用。

因此不会有使用 strftime() 的解决方案。幸运的是,“手动”执行此操作非常简单:

>>> "%02d-%02d-%02d %02d:%02d" % (d.year,d.month,d.day,d.hour,d.minute)
'1899-01-01 00:00'

The documentation seems pretty clear about this:

The exact range of years for which strftime() works also varies across platforms. Regardless of platform, years before 1900 cannot be used.

So there isn't going to be a solution that uses strftime(). Luckily, it's pretty straightforward to do this "by hand":

>>> "%02d-%02d-%02d %02d:%02d" % (d.year,d.month,d.day,d.hour,d.minute)
'1899-01-01 00:00'
温折酒 2024-08-16 05:52:45

mxDateTime 可以处理任意日期。 Python 的 timedatetime 模块在内部使用 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

mxDateTime can handle arbitrary dates. Python's time and datetime modules use UNIX timestamps internally, that's why they have limited range.

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
北凤男飞 2024-08-16 05:52:45

这是来自 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)

This is from the matplotlib source. Could provide a good starting point for rolling your own.

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)
紫竹語嫣☆ 2024-08-16 05:52:45

这就是ctime库(UTF)的“特性”。
另外你可能会在 2038 以上遇到问题。

This is the "feature" of the ctime library (UTF).
Also You may have problem above 2038.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文