6

Using pytz and Python 3.4, how to get the first datetime of a given day (lets say, 2014-10-19), in a given timezone (lets say 'America/Sao_Paulo')?

lvella
  • 12,754
  • 11
  • 54
  • 106
  • 1
    Have you a list of `datetime`s? What do you mean with first? – Daniel Jan 04 '15 at 21:24
  • there are numerous ways to interpret this question, some input and expected output would make it a lot more obvious what you are trying to do. – Padraic Cunningham Jan 04 '15 at 21:31
  • By first, I mean the datetime in that day and timezone that is not greater than any other datetime on that day and timezone. – lvella Jan 05 '15 at 00:40
  • 1
    related: [How do I get the UTC time of “midnight” for a given timezone?](http://stackoverflow.com/q/373370/4279) – jfs Jan 05 '15 at 08:47

1 Answers1

5

Use localize() method to attach the timezone:

from datetime import datetime
import pytz # $ pip install pytz

tz = pytz.timezone('America/Sao_Paulo')    
naive = datetime(2014, 10, 19)
aware = tz.localize(naive, is_dst=None)

If you run the code; it generates NonExistentTimeError. How to deal with this error depends on the application e.g., to get some valid local time near the midnight:

aware = tz.normalize(tz.localize(naive, is_dst=False))

Or you could increment the time minute by minute until you'll get a valid local (Sao Paulo) time:

from datetime import datetime, timedelta
import pytz # $ pip install pytz

tz = pytz.timezone('America/Sao_Paulo')
d = naive = datetime(2014, 10, 19)
while True:
    try:
        aware = tz.localize(d, is_dst=None)
    except pytz.AmbiguousTimeError:
        aware = tz.localize(d, is_dst=False)
        assert tz.localize(d, is_dst=False) > tz.localize(d, is_dst=True)
        break
    except pytz.NonExistentTimeError:
        d += timedelta(minutes=1) # try future time
        continue
    else:
        break

Result:

>>> aware
datetime.datetime(2014, 10, 19, 1, 0, tzinfo=<DstTzInfo 'America/Sao_Paulo' BRST-1 day, 22:00:00 DST>
>>> aware.strftime('%Y-%m-%d %H:%M:%S %Z%z')
'2014-10-19 01:00:00 BRST-0200'

Note: the first valid time is 01:00 on that day. And the timezone is two hours behind UTC (local = utc - 2).

jfs
  • 399,953
  • 195
  • 994
  • 1,670