views:

2892

answers:

3

I'm using the Python "datetime" module, i.e.:

>>> import datetime
>>> today = datetime.datetime.now()
>>> print today
2009-03-06 13:24:58.857946

and I would like to compute the day of year that is sensitive of leap years. e.g. oday (March 6, 2009) is the 65th day of 2009. Here's web-based DateTime calculator.

Anyway, I see a two options:

  1. Create a number_of_days_in_month array = [31, 28, ...], decide if it's a leap year, manually sum up the days

  2. Use datetime.timedelta to make a guess & then binary search for the correct day of year:

.

>>> import datetime
>>> YEAR = 2009
>>> DAY_OF_YEAR = 62
>>> d = datetime.date(YEAR, 1, 1) + datetime.timedelta(DAY_OF_YEAR - 1)

These both feel pretty clunky & I have a gut feeling that there's a more "Pythonic" way of calculating day of year. Any ideas/suggestions?

+5  A: 

Couldn't you use strftime?

>>> import datetime
>>> today = datetime.datetime.now()
>>> print today
2009-03-06 15:37:02.484000
>>> today.strftime('%j')
'065'

Edit

As noted in the comments, if you wish to do comparisons or calculations with this number, you would have to convert it to int() because strftime() returns a string. If that is the case, you are better off using DzinX's answer.

Paolo Bergantino
Brilliant--I knew there was some obvious way of doing it. Thanks!
Pete
-1: icky. Better is the "today minus january 1st" algorithm. Much cleaner and perfectly obvious without looking up a piece of trivia about strftime's '%j'.
S.Lott
Seriously? How is this icky and substracting january 1st isn't? strftime is there for a reason. I just don't agree. This is WAY cleaner in my opinion.
Paolo Bergantino
Using strftime is indirect, because it produces a string from a number: the timetuple.tm_yday member. Read the source. The produced string should be converted to a number before any calculations/comparisons, so why bother?
ΤΖΩΤΖΙΟΥ
+2  A: 

Just subtract january 1 from the date:

import datetime
today = datetime.datetime.now()
day_of_year = (today - datetime.datetime(today.year, 1, 1)).days + 1
zweiterlinde
+1: The standard, correct algorithm.
S.Lott
Cute, but hardly "The standard, correct algorithm."
Matthew Schinckel
Nothing against Paolo, but datetime.timedelta is denominated in days (as well as seconds and microseconds, of course), so it's a natural choice---certainly more direct than string formatting
zweiterlinde
d.toordinal() - date(d.year, 1, 1).toordinal() + 1 is more standard according to the documentation. It is equivalent to the accepted answer without producing the whole time tuple.
Dingle
+21  A: 

There is a very simple solution:

day_of_year = datetime.now().timetuple().tm_yday
DzinX