user9132502
user9132502

Reputation: 385

How to get timestamp in UTC in Python

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: 2713

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1124488

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 C mktime() 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 supplying tzinfo=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

Related Questions