Reputation: 385
I'm using an API that has an endpoint that can be filtered by date. The date needs to be in timestamp in seconds since epoch and it must be in UTC so that the API can be properly filtered
This is what I've tried as of today
first_day = datetime.utcnow().replace(day=1)
first_day = first_day.replace(hour=0, minute=0, second=0, microsecond=0)
print(first_day, int(first_day.timestamp()))
last_day = datetime.utcnow().replace(day=calendar.monthrange(datetime.utcnow().year, datetime.utcnow().month)[1])
last_day = last_day.replace(hour=0, minute=0, second=0, microsecond=0)
print(last_day, int(last_day.timestamp()))
This is my output
2019-01-01 00:00:00 1546318800
2019-01-31 00:00:00 1548910800
And then when I take the gotten timestamp 1546318800 for the first day of January and then I go to https://www.epochconverter.com/ and paste it to human date I get the following:
GMT: Tuesday, January 1, 2019 5:00:00 AM Your time zone: Tuesday, January 1, 2019 12:00:00 AM GMT-05:00
I want the GMT time to be January 1, 2019 12:00:00 AM
How can I accomplish this?
Upvotes: 0
Views: 2714
Reputation: 1124558
You are working with naive datetime
objects. For a naive datetime
object, the time is assumed to be in local time, and so your local system timezone offset is first applied. From the `datetime.timestamp() documentation:
Naive
datetime
instances are assumed to represent local time and this method relies on the platform Cmktime()
function to perform the conversion.
and further on:
Note: There is no method to obtain the POSIX timestamp directly from a naive
datetime
instance representing UTC time. If your application uses this convention and your system timezone is not set to UTC, you can obtain the POSIX timestamp by supplyingtzinfo=timezone.utc
:timestamp = dt.replace(tzinfo=timezone.utc).timestamp()
Note that you can make your date calculation logic much easier by working with daetime.date
objects and using datetime.combine()
; this method also accepts a new timezone value, so you can pass in the timezone.utc
timezone at this stage:
from datetime import datetime, date, time, timedelta, timezone
# create first and last day of the month
first_day = date.today().replace(day=1)
last_day = (first_day + timedelta(days=31)).replace(day=1) - timedelta(days=1)
first_day = int(datetime.combine(first_day, time.min, tzinfo=timezone.utc).timestamp())
last_day = int(datetime.combine(last_day, time.min, tzinfo=timezone.utc).timestamp())
The above calculates the last day of the month by first adding 31 days (guaranteed to reach the next month whatever the current), then dropping that new date down to the first day of the month and then subtracting one day.
Demo:
>>> from datetime import datetime, date, time, timedelta, timezone
>>> first_day = date.today().replace(day=1)
>>> last_day = (first_day + timedelta(days=31)).replace(day=1) - timedelta(days=1)
>>> first_day, last_day
(datetime.date(2019, 1, 1), datetime.date(2019, 1, 31))
>>> int(datetime.combine(first_day, time.min, tzinfo=timezone.utc).timestamp())
1546300800
>>> int(datetime.combine(last_day, time.min, tzinfo=timezone.utc).timestamp())
1548892800
Note that midnight on the 31st of January leaves another 24 hours of the month left uncovered. You may want to remove the - timedelta(days=1)
subtraction off of the last_day
calculation above to switch to February 1st midnight (1548979200), or use time.max
to shift the timestamp to 23:23:59 (1 second before midnight) on the 31st (1548979199).
Upvotes: 2