Есть ли способ использовать strftime-подобную функцию для дат до 1900 года в Python?

StackOverflow https://stackoverflow.com/questions/1643967

Вопрос

Я этого не осознавал, но, очевидно, функция 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 есть по причине (и есть также причина, по которой она не может поддерживать предварительно 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 ('') .

Это было полезно?

Решение

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 года.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top