36

I used : utctime = datetime.datetime(1601,1,1) + datetime.timedelta(microseconds = tup[5]) last_visit_time = "Last visit time:"+ utctime.strftime('%Y-%m-%d %H:%M:%S')

But I have the time of 1601, so the error show: ValueError: year=1601 is before 1900; the datetime strftime() methods require year >= 1900

I used python2.7, how can I make it? Thanks a lot!

Alex
  • 869
  • 3
  • 13
  • 20
  • 4
    You will need an external library. mxDateTime does dates back to year 0. http://www.egenix.com/products/python/mxBase/mxDateTime/doc/ – Steven Rumbalski Apr 21 '12 at 23:36

4 Answers4

22

You can do the following:

>>> utctime.isoformat()
'1601-01-01T00:00:00.000050'

Now if you want to have exactly the same format as above:

iso = utctime.isoformat()
tokens = iso.strip().split("T")
last_visit_time = "Last visit time: %s %s" % (tokens[0], tokens[1].strip().split(".")[0])

Not that there seems to be a patch for strftime to fix this behavior here (not tested)

Charles Menguy
  • 40,830
  • 17
  • 95
  • 117
14

the isoformat method accepts a parameter specifing the character(s) dividing the date part from the time part of a datetime obj in its representation. Therefore:

>>> utctime.isoformat(" ")
'1601-01-01 00:00:00.000050'

should do it. Furthermore, if you want to remove the microseconds you can operate a split.

>>> utctime.isoformat(" ").split(".")[0]
'1601-01-01 00:00:00'
12

There are various ways to alter strftime so that it handles pre-1900 dates:

  • There's a recipe at ASPN that gives you a separate strftime method that you can call with a date object: aspn_recipe.strftime(dt, fmt) if you set it up in a module yourself
  • As @stephen-rumbalski said, the external mxDateTime package supports this; but that's using a totally different date object system
  • As of version 1.5, the virtualtime package will patch both time.strftime and datetime.datetime.strftime to behave as in Python 3.3+. You can take advantage of this without enabling the other virtual time functions. (Disclaimer: I work on this package)

Note that Python 2.7, 3.0 and 3.1 have errors before the year 1900, Python 3.2 has errors before the year 1000. Additionally, pre-3.2 versions interpret years between 0 and 99 as between 1969 and 2068. Python versions from 3.3 onward support all positive years in datetime (and negative years in time.strftime), and time.strftime doesn't do any mapping of years between 0 and 99.

The original Python bug explains that they decided that this was a feature in Python 2.7 (presumably since it avoided lack of system strftime support for these dates), and then gradually worked on it in the Python 3 series, by reimplementing functionality.

Community
  • 1
  • 1
David Fraser
  • 6,475
  • 1
  • 40
  • 56
  • I tried the virtualtime monkeypatcher, but I can't find any documentation and I can't figure out what i need to do to make it go. – Scott Stafford Sep 27 '17 at 17:24
  • 2
    I used `sudo pip install virtualtime` to install it, then imported it with `import virtualtime` and called `virtualtime.enable()`. Worked great! – nickb Jan 21 '18 at 21:11
  • 1
    virtualtime saved the day – Roman M Jul 12 '18 at 07:14
  • I tried the `import virtualtime` / `virtualtime.enable()` approach. For reasons I don't entirely understand, it made all the `DateTimeField`s in my Django models save only the date and not the time in Postgres. virtuatime 1.6, Django 1.11.13. – TAH Feb 15 '19 at 04:47
8

I recommend using arrow (which is an abstraction package on datetime and dateutil), it's really easy to handle every kind of datetime objects, even in Python 2.6/7.x and with dates prior to 1900.

For example:

>>> import arrow

>>> in_date_str = "1853-10-30T13:36:41.942623+00:00"
>>> in_date_obj = arrow.get(crea)
>>> print(in_date_obj)
arrow[1853-10-30T13:36:41.942623+00:00]>

# basic formatting
>>> in_date_obj.format()
u'1853-10-30 13:36:41-00:00'

# advanced formatting
>>> in_date_obj.format("dddd D MMMM YYYY", "fr_FR")
u'Dimanche 30 Octobre 1853'

# humanized delta
>>> in_date_obj.humanize()
u'162 years ago'
# easy localization handling
>>> in_date_obj.humanize(locale="fr_FR")
u'il y a 162 ans'
Guts
  • 892
  • 8
  • 9