I am storing all my times in UTC and my system is set to UTC (though I am in EST).

I have dates stored as:

Wed, 20 Feb 2013 03:51:39 +0000

However, I would like to select information based off today for EST, so I am attempting to:

  • Get current time as UTC and change to EST

    datetime.utcnow().replace(tzinfo=tz.tzutc()).astimezone(tz.gettz('America/New_York'))
    2013-02-19 23:17:20.560898-05:00
    
  • Next I want to get the start time for the EST day (2013-02-19 00:00:00.000000-05:00) and the end time (2013-02-19 23:59:59.99999-05:00)

  • Once I have those values, I’d like to convert back to UTC, so I have a high and low value I can clamp by that’s correct my EST (my timezone).

If this isn’t the best way to do this, or I’m missing something (does seem overly complicated to me) please help me see the light!

TIA

Update per answer:

d1 = datetime.utcnow().replace(tzinfo=tz.tzutc()).astimezone(tz.gettz('America/New_York'))
print d1.strftime("%m %d %Y") ; d2 = d1.replace(day=d1.day + 1) ; print d2.strftime("%m %d %Y")

That will give me

02 20 2013
02 21 2013

Which is correct. I now need to generate the full EST time from that and then convert to UTC. This I cannot figure out. Actually, I probably want to convert to UTC epoch timestamp when complete because that will make my database operations pretty easy (<, >, ==, etc).

The first step of getting current time as UTC and converting it to EST seems a bit pointless. Do you use that time for anything?

Other than that it seems rather straighforward. You want to get the start and end of a day EST in UTC, so you create them and convert them to UTC. That’s not so complicated. πŸ™‚

You might want to look at your matching routines though, so that you can use the start of today as the lower value, and the start of tomorrow as the higher, so you don’t have to deal with that 23:59:59.9999 time.

Update:

From my original understanding of your question, this is what you want to do:

First you want to get the current date as it is in UTC (so at 11pm EST the 12st, you want the 22nd, as it is the 22nd in UTC then.

>>> from datetime import datetime
>>> today = datetime.utcnow().date()
>>> today
datetime.date(2013, 2, 21)

Secondly you want 00:00:00 of that day in UTC, as start for a search.

>>> from dateutil import tz
>>> start = datetime(today.year, today.month, today.day, tzinfo=tz.tzutc())
datetime.datetime(2013, 2, 21, 0, 0, tzinfo=tzutc())

Except that you want to know what that time is in New York:

>>> from dateutil import tz
>>> est = tz.gettz('America/New_York')
>>> start = start.astimezone(est)
>>> start
datetime.datetime(2013, 2, 20, 19, 0, tzinfo=tzfile('/usr/share/zoneinfo/America/New_York'))

And you also want tomorrow as the end:

>>> from datetime import timedelta
>>> end = start + timedelta(1)
>>> end
datetime.datetime(2013, 2, 21, 19, 0, tzinfo=tzfile('/usr/share/zoneinfo/America/New_York'))

Summary:

today = datetime.utcnow().date()
start = datetime(today.year, today.month, today.day, tzinfo=tz.tzutc()).astimezone(est)
end = start + timedelta(1)

use datetime pytz will solve your problem.

def get_start_and_end():
    tz = pytz.timezone('Asia/Shanghai')
    today = datetime.now(tz=tz)
    start = today.replace(hour=0, minute=0, second=0, microsecond=0)
    end = start + timedelta(1)

    return start, end

I would definitely give Delorean a look, to solve your problem would follow a few steps.

You first need to parse your string. Excellent use the Delorean parse method.

>>> from delorean import parse
>>> d = parse("Wed, 20 Feb 2013 03:51:39 +0000")
>>> d
Delorean(datetime=2013-02-20 03:51:39+00:00, timezone=UTC)

Once you have the datetime that you parsed in a Delorean object you simply convert to EST

>>> d = d.shift('US/Eastern')
>>> d
Delorean(datetime=2013-02-19 22:51:39-05:00, timezone=US/Eastern)

Albeit pointless. You never use it for anything in your question, but super easy with Delorean.

Then you get the time now in EST

from delorean import Delorean

>>> d1 = Delorean(timezone="US/Eastern")
>>> d1
Delorean(datetime=2013-02-21 00:35:56.405256-05:00, timezone=US/Eastern)

Now for the truncation step.

>>> d.truncate('day')
Delorean(datetime=2013-02-21 00:00:00-05:00, timezone=US/Eastern)

do the simple shift as above to UTC.

Now get the end of day.

d = d.next_day(1) # move to the next day

Then to shift back one second. Something that the library needs I will be updating this. Simply get the datetime from the Delorean example by asking for it with datetime attribute.

d.datetime - timedelta(seconds=1)
datetime.datetime(2013, 2, 21, 23, 59, 59, tzinfo=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>)

Goodluck, but this library should simply your dealing with datetime operations πŸ™‚

This is only a partial answer, because the rest has been covered well. I struggled with this for a while, as some technologies have inclusive searches, and I don’t want to include any data from the first microsecond of the next day.

My solution for finding the end of day time quickly and correctly is this:

reference_time.replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(days=1,microseconds=-1)

The question is old but maybe this helps:

import datetime
end_of_today = datetime.datetime.combine(datetime.datetime.today(), datetime.time(23, 59, 59, 999999))

Just ran into this, here’s the simplest option I found:

from delorean import Delorean
today_d = Delorean()
sod_dt = today_d.start_of_day
eod_dt = today_d.end_of_day
sod_d = Delorean(sod_dt)
eod_d = Delorean(eod_dt)
sod_e = sod_d.epoch
eod_e = eod_d.epoch

to confirm:

In [69]: eod_e - sod_e
Out[69]: 86399.99999904633

close enough for most people

How about this

import datetime
datetime.datetime.combine(datetime.date.today(), datetime.time(00, 00, 00))
datetime.datetime.combine(datetime.date.today(), datetime.time(23, 59, 59))

Here’s a nice solution if you already use Arrow.

import arrow

now = arrow.now('US/Eastern')
start = now.floor('day')
end = now.ceil('day')

# Use the "datetime" property to access the actual datetime
print(start.datetime)

Simplest solution for getting the start of a day, though it might produce a phantom microsecond in unlucky floating point imprecision cases:

import datetime as dt
d = dt.datetime.now()
d = d - dt.timedelta(seconds=d.timestamp() % dt.timedelta(days=1).total_seconds())

With python3.8, we can use as follow:

from datetime import datetime, timedelta, time
from pytz import timezone

today = datetime.utcnow()
start_of_day = datetime.combine(today, time.min).astimezone(tz=timezone('America/New_York'))
end_of_day = datetime.combine(today, time.max).astimezone(tz=timezone('America/New_York'))