How do I convert a datetime string in local time to a string in UTC time?
I'm sure I've done this before, but can't find it and SO will hopefully help me (and others) do that in future.
Clarification: For example, if I have 2008-09-17 14:02:00
in my local timezone (+10
), I'd like to generate a string with the equivalent UTC
time: 2008-09-17 04:02:00
.
Also, from http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/, note that in general this isn't possible as with DST and other issues there is no unique conversion from local time to UTC time.
First, parse the string into a naive datetime object. This is an instance of datetime.datetime
with no attached timezone information. See its documentation.
Use the pytz
module, which comes with a full list of time zones + UTC. Figure out what the local timezone is, construct a timezone object from it, and manipulate and attach it to the naive datetime.
Finally, use datetime.astimezone()
method to convert the datetime to UTC.
Source code, using local timezone "America/Los_Angeles", for the string "2001-2-3 10:11:12":
from datetime import datetime
import pytz
local = pytz.timezone("America/Los_Angeles")
naive = datetime.strptime("2001-2-3 10:11:12", "%Y-%m-%d %H:%M:%S")
local_dt = local.localize(naive, is_dst=None)
utc_dt = local_dt.astimezone(pytz.utc)
From there, you can use the strftime()
method to format the UTC datetime as needed:
utc_dt.strftime("%Y-%m-%d %H:%M:%S")
NOTE -- As of 2020 you should not be using .utcnow()
or .utcfromtimestamp(xxx)
. As you've presumably moved on to python3,you should be using timezone aware datetime objects.
>>> from datetime import timezone
>>>
>>> # alternative to '.utcnow()'
>>> dt_now = datetime.datetime.now(datetime.timezone.utc)
>>>
>>> # alternative to '.utcfromtimestamp()'
>>> dt_ts = datetime.fromtimestamp(1571595618.0, tz=timezone.utc)
for details see: see: https://blog.ganssle.io/articles/2019/11/utcnow.html
original answer (from 2010):
The datetime module's utcnow() function can be used to obtain the current UTC time.
>>> import datetime
>>> utc_datetime = datetime.datetime.utcnow()
>>> utc_datetime.strftime("%Y-%m-%d %H:%M:%S")
'2010-02-01 06:59:19'
As the link mentioned above by Tom: http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/ says:
UTC is a timezone without daylight saving time and still a timezone without configuration changes in the past. Always measure and store time in UTC. If you need to record where the time was taken, store that separately. Do not store the local time + timezone information!
NOTE - If any of your data is in a region that uses DST, use pytz
and take a look at John Millikin's answer.
If you want to obtain the UTC time from a given string and your lucky enough to be in a region in the world that either doesn't use DST, or you have data that is only offset from UTC without DST applied:
--> using local time as the basis for the offset value:
>>> # Obtain the UTC Offset for the current system:
>>> UTC_OFFSET_TIMEDELTA = datetime.datetime.utcnow() - datetime.datetime.now()
>>> local_datetime = datetime.datetime.strptime("2008-09-17 14:04:00", "%Y-%m-%d %H:%M:%S")
>>> result_utc_datetime = local_datetime + UTC_OFFSET_TIMEDELTA
>>> result_utc_datetime.strftime("%Y-%m-%d %H:%M:%S")
'2008-09-17 04:04:00'
--> Or, from a known offset, using datetime.timedelta():
>>> UTC_OFFSET = 10
>>> result_utc_datetime = local_datetime - datetime.timedelta(hours=UTC_OFFSET)
>>> result_utc_datetime.strftime("%Y-%m-%d %H:%M:%S")
'2008-09-17 04:04:00'
UPDATE:
Since python 3.2 datetime.timezone
is available. You can generate a timezone aware datetime object with the command below:
import datetime
timezone_aware_dt = datetime.datetime.now(datetime.timezone.utc)
If your ready to take on timezone conversions go read this:
tzinfo.utcoffset() must return a whole number of minutes
and so on.
Thanks @rofly, the full conversion from string to string is as follows:
time.strftime("%Y-%m-%d %H:%M:%S",
time.gmtime(time.mktime(time.strptime("2008-09-17 14:04:00",
"%Y-%m-%d %H:%M:%S"))))
My summary of the time
/calendar
functions:
time.strptime
string --> tuple (no timezone applied, so matches string)
time.mktime
local time tuple --> seconds since epoch (always local time)
time.gmtime
seconds since epoch --> tuple in UTC
and
calendar.timegm
tuple in UTC --> seconds since epoch
time.localtime
seconds since epoch --> tuple in local timezone
(always local time)
seems to be wrong: the input to mktime() is local time, the output is seconds since epoch (1970-01-01 00:00:00 +0000 (UTC)
) that doesn't depend on timezone.
Here's a summary of common Python time conversions.
Some methods drop fractions of seconds, and are marked with (s). An explicit formula such as ts = (d - epoch) / unit
can be used instead (thanks jfs).
struct_time (UTC) → POSIX (s): calendar.timegm(struct_time)
Naïve datetime (local) → POSIX (s): calendar.timegm(stz.localize(dt, is_dst=None).utctimetuple()) (exception during DST transitions, see comment from jfs)
Naïve datetime (UTC) → POSIX (s): calendar.timegm(dt.utctimetuple())
Aware datetime → POSIX (s): calendar.timegm(dt.utctimetuple())
POSIX → struct_time (UTC, s): time.gmtime(t) (see comment from jfs)
Naïve datetime (local) → struct_time (UTC, s): stz.localize(dt, is_dst=None).utctimetuple() (exception during DST transitions, see comment from jfs)
Naïve datetime (UTC) → struct_time (UTC, s): dt.utctimetuple()
Aware datetime → struct_time (UTC, s): dt.utctimetuple()
POSIX → Naïve datetime (local): datetime.fromtimestamp(t, None) (may fail in certain conditions, see comment from jfs below)
struct_time (UTC) → Naïve datetime (local, s): datetime.datetime(struct_time[:6], tzinfo=UTC).astimezone(tz).replace(tzinfo=None) (can't represent leap seconds, see comment from jfs)
Naïve datetime (UTC) → Naïve datetime (local): dt.replace(tzinfo=UTC).astimezone(tz).replace(tzinfo=None)
Aware datetime → Naïve datetime (local): dt.astimezone(tz).replace(tzinfo=None)
POSIX → Naïve datetime (UTC): datetime.utcfromtimestamp(t)
struct_time (UTC) → Naïve datetime (UTC, s): datetime.datetime(*struct_time[:6]) (can't represent leap seconds, see comment from jfs)
Naïve datetime (local) → Naïve datetime (UTC): stz.localize(dt, is_dst=None).astimezone(UTC).replace(tzinfo=None) (exception during DST transitions, see comment from jfs)
Aware datetime → Naïve datetime (UTC): dt.astimezone(UTC).replace(tzinfo=None)
POSIX → Aware datetime: datetime.fromtimestamp(t, tz) (may fail for non-pytz timezones)
struct_time (UTC) → Aware datetime (s): datetime.datetime(struct_time[:6], tzinfo=UTC).astimezone(tz) (can't represent leap seconds, see comment from jfs)
Naïve datetime (local) → Aware datetime: stz.localize(dt, is_dst=None) (exception during DST transitions, see comment from jfs)
Naïve datetime (UTC) → Aware datetime: dt.replace(tzinfo=UTC)
Source: taaviburns.ca
fromtimestamp(t, None)
may fail if the local timezone had different utc offset at t
and C library has no access to the tz database on the given platform. You could use tzlocal.get_localzone()
to provide tzdata in a portable way. (2) fromtimestamp(t, tz)
may fail for non-pytz timezones. (3) datetime(*struct_time[:6])
you are missing *
. (4) timegm()
, utctimetuple()
, struct_time
-based solutions drop fractions of a second. You could use an explicit formula such as: ts = (d - epoch) / unit
instead.
stz.localize(dt, is_dst=None)
raises an exception for ambiguous or non-existent local times e.g., during DST transitions. To avoid the exception, use stz.normalize(stz.localize(dt))
that may return imprecise results. (6) datetime() can't represent a leap second. Convert struct_time
to "seconds since epoch" as a workaround first. (7) time.gmtime(t)
unlike calendar.timegm()
may expect non-POSIX input if "right" timezone is used. Use the explicit formula if the input is POSIX instead: gmtime = lambda t: datetime(1970,1,1, tzinfo=utc) + timedelta(seconds=t)
<table>
tags. Sorry. This is intentional and by design. If you need a quick and dirty "table", use <pre>
and ASCII layout." I don't believe an ASCII table would be more readable than the list above.
I'm having good luck with dateutil (which is widely recommended on SO for other related questions):
from datetime import *
from dateutil import *
from dateutil.tz import *
# METHOD 1: Hardcode zones:
utc_zone = tz.gettz('UTC')
local_zone = tz.gettz('America/Chicago')
# METHOD 2: Auto-detect zones:
utc_zone = tz.tzutc()
local_zone = tz.tzlocal()
# Convert time string to datetime
local_time = datetime.strptime("2008-09-17 14:02:00", '%Y-%m-%d %H:%M:%S')
# Tell the datetime object that it's in local time zone since
# datetime objects are 'naive' by default
local_time = local_time.replace(tzinfo=local_zone)
# Convert time to UTC
utc_time = local_time.astimezone(utc_zone)
# Generate UTC time string
utc_string = utc_time.strftime('%Y-%m-%d %H:%M:%S')
(Code was derived from this answer to Convert UTC datetime string to local datetime)
dateutil
can fail for past dates if local timezone had different utc offset then (unrelated to DST transitions) on systems where the implementation doesn't use a historical timezone database (notably Windows). pytz
+ tzlocal
could be used instead.
def local_to_utc(t):
secs = time.mktime(t)
return time.gmtime(secs)
def utc_to_local(t):
secs = calendar.timegm(t)
return time.localtime(secs)
Source: http://feihonghsu.blogspot.com/2008/02/converting-from-local-time-to-utc.html
Example usage from bd808: If your source is a datetime.datetime
object t
, call as:
local_to_utc(t.timetuple())
t
, call as: local_to_utc(t.timetuple())
.timetuple()
call sets tm_isdst
to -1
; there is 50% chance mktime()
fails during DST transition.
One more example with pytz, but includes localize(), which saved my day.
import pytz, datetime
utc = pytz.utc
fmt = '%Y-%m-%d %H:%M:%S'
amsterdam = pytz.timezone('Europe/Amsterdam')
dt = datetime.datetime.strptime("2012-04-06 10:00:00", fmt)
am_dt = amsterdam.localize(dt)
print am_dt.astimezone(utc).strftime(fmt)
'2012-04-06 08:00:00'
An option available since Python 3.6: datetime.astimezone(tz=None)
can be used to get an aware datetime object representing local time (docs). This can then easily be converted to UTC.
from datetime import datetime, timezone
s = "2008-09-17 14:02:00"
# to datetime object:
dt = datetime.fromisoformat(s) # Python 3.7
# I'm on time zone Europe/Berlin; CEST/UTC+2 during summer 2008
dt = dt.astimezone()
print(dt)
# 2008-09-17 14:02:00+02:00
# ...and to UTC:
dtutc = dt.astimezone(timezone.utc)
print(dtutc)
# 2008-09-17 12:02:00+00:00
Side-Note: While the described conversion to UTC works perfectly fine, .astimezone()
sets tzinfo
of the datetime object to a timedelta-derived timezone - so don't expect any "DST-awareness" from it.
I've had the most success with python-dateutil:
from dateutil import tz
def datetime_to_utc(date):
"""Returns date in UTC w/o tzinfo"""
return date.astimezone(tz.gettz('UTC')).replace(tzinfo=None) if date.tzinfo else date
import time
import datetime
def Local2UTC(LocalTime):
EpochSecond = time.mktime(LocalTime.timetuple())
utcTime = datetime.datetime.utcfromtimestamp(EpochSecond)
return utcTime
>>> LocalTime = datetime.datetime.now()
>>> UTCTime = Local2UTC(LocalTime)
>>> LocalTime.ctime()
'Thu Feb 3 22:33:46 2011'
>>> UTCTime.ctime()
'Fri Feb 4 05:33:46 2011'
mktime(dt.timetuple())
can fail during DST transition. There is LocalTimezone
in the docs (it works for the most recent timezone definition but can fail for past dates (unrelated to DST))
if you prefer datetime.datetime:
dt = datetime.strptime("2008-09-17 14:04:00","%Y-%m-%d %H:%M:%S")
utc_struct_time = time.gmtime(time.mktime(dt.timetuple()))
utc_dt = datetime.fromtimestamp(time.mktime(utc_struct_time))
print dt.strftime("%Y-%m-%d %H:%M:%S")
mktime()
expects local time as the input. fromtimestamp()
returns local time, not utc. If you fix it then see these additional issues (like dateutil
, stdlib-only solution may fail)
Simple
I did it like this:
>>> utc_delta = datetime.utcnow()-datetime.now()
>>> utc_time = datetime(2008, 9, 17, 14, 2, 0) + utc_delta
>>> print(utc_time)
2008-09-17 19:01:59.999996
Fancy Implementation
If you want to get fancy, you can turn this into a functor:
class to_utc():
utc_delta = datetime.utcnow() - datetime.now()
def __call__(cls, t):
return t + cls.utc_delta
Result:
>>> utc_converter = to_utc()
>>> print(utc_converter(datetime(2008, 9, 17, 14, 2, 0)))
2008-09-17 19:01:59.999996
How about -
time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(seconds))
if seconds is None
then it converts the local time to UTC time else converts the passed in time to UTC.
You can do it with:
>>> from time import strftime, gmtime, localtime
>>> strftime('%H:%M:%S', gmtime()) #UTC time
>>> strftime('%H:%M:%S', localtime()) # localtime
Here's an example with the native zoneinfo module in Python3.9:
from datetime import datetime
from zoneinfo import ZoneInfo
# Get timezone we're trying to convert from
local_tz = ZoneInfo("America/New_York")
# UTC timezone
utc_tz = ZoneInfo("UTC")
dt = datetime.strptime("2021-09-20 17:20:00","%Y-%m-%d %H:%M:%S")
dt = dt.replace(tzinfo=local_tz)
dt_utc = dt.astimezone(utc_tz)
print(dt.strftime("%Y-%m-%d %H:%M:%S"))
print(dt_utc.strftime("%Y-%m-%d %H:%M:%S"))
This may be preferred over just using dt.astimezone()
in situations where the timezone you're converting from isn't reflective of your system's local timezone. Not having to rely on external libraries is nice too.
Note: This may not work on Windows systems, since zoneinfo relies on an IANA database that may not be present. The tzdata package can be installed as a workaround. It's a first-party package, but is not in the standard library.
For getting around day-light saving, etc.
None of the above answers particularly helped me. The code below works for GMT.
def get_utc_from_local(date_time, local_tz=None):
assert date_time.__class__.__name__ == 'datetime'
if local_tz is None:
local_tz = pytz.timezone(settings.TIME_ZONE) # Django eg, "Europe/London"
local_time = local_tz.normalize(local_tz.localize(date_time))
return local_time.astimezone(pytz.utc)
import pytz
from datetime import datetime
summer_11_am = datetime(2011, 7, 1, 11)
get_utc_from_local(summer_11_am)
>>>datetime.datetime(2011, 7, 1, 10, 0, tzinfo=<UTC>)
winter_11_am = datetime(2011, 11, 11, 11)
get_utc_from_local(winter_11_am)
>>>datetime.datetime(2011, 11, 11, 11, 0, tzinfo=<UTC>)
Using http://crsmithdev.com/arrow/
arrowObj = arrow.Arrow.strptime('2017-02-20 10:00:00', '%Y-%m-%d %H:%M:%S' , 'US/Eastern')
arrowObj.to('UTC') or arrowObj.to('local')
This library makes life easy :)
I have this code in one of my projects:
from datetime import datetime
## datetime.timezone works in newer versions of python
try:
from datetime import timezone
utc_tz = timezone.utc
except:
import pytz
utc_tz = pytz.utc
def _to_utc_date_string(ts):
# type (Union[date,datetime]]) -> str
"""coerce datetimes to UTC (assume localtime if nothing is given)"""
if (isinstance(ts, datetime)):
try:
## in python 3.6 and higher, ts.astimezone() will assume a
## naive timestamp is localtime (and so do we)
ts = ts.astimezone(utc_tz)
except:
## in python 2.7 and 3.5, ts.astimezone() will fail on
## naive timestamps, but we'd like to assume they are
## localtime
import tzlocal
ts = tzlocal.get_localzone().localize(ts).astimezone(utc_tz)
return ts.strftime("%Y%m%dT%H%M%SZ")
In python 3.9.0, after you've parsed your local time local_time
into datetime.datetime
object, just use local_time.astimezone(datetime.timezone.utc)
.
I found the best answer on another question here. It only uses python built-in libraries and does not require you to input your local timezone (a requirement in my case)
import time
import calendar
local_time = time.strptime("2018-12-13T09:32:00.000", "%Y-%m-%dT%H:%M:%S.%f")
local_seconds = time.mktime(local_time)
utc_time = time.gmtime(local_seconds)
I'm reposting the answer here since this question pops up in google instead of the linked question depending on the search keywords.
If you already have a datetime object my_dt
you can change it to UTC with:
datetime.datetime.utcfromtimestamp(my_dt.timestamp())
For anyone who is confused with the most upvoted answer. You can convert a datetime string to utc time in python by generating a datetime object and then you can use astimezone(pytz.utc) to get datetime in utc.
For eg.
let say we have local datetime string as 2021-09-02T19:02:00Z
in isoformat
Now to convert this string to utc datetime. we first need to generate datetime object using this string by
dt = datetime.strptime(dt,'%Y-%m-%dT%H:%M:%SZ')
this will give you python datetime object, then you can use astimezone(pytz.utc)
to get utc datetime like
dt = datetime.strptime(dt,'%Y-%m-%dT%H:%M:%SZ') dt = dt.astimezone(pytz.utc)
this will give you datetime object in utc, then you can convert it to string using dt.strftime("%Y-%m-%d %H:%M:%S")
full code eg:
from datetime import datetime
import pytz
def converLocalToUTC(datetime, getString=True, format="%Y-%m-%d %H:%M:%S"):
dt = datetime.strptime(dt,'%Y-%m-%dT%H:%M:%SZ')
dt = dt.astimezone(pytz.utc)
if getString:
return dt.strftime(format)
return dt
then you can call it as
converLocalToUTC("2021-09-02T19:02:00Z")
took help from https://stackoverflow.com/a/79877/7756843
Briefly, to convert any datetime
date to UTC time:
from datetime import datetime
def to_utc(date):
return datetime(*date.utctimetuple()[:6])
Let's explain with an example. First, we need to create a datetime
from the string:
>>> date = datetime.strptime("11 Feb 2011 17:33:54 -0800", "%d %b %Y %H:%M:%S %z")
Then, we can call the function:
>>> to_utc(date)
datetime.datetime(2011, 2, 12, 1, 33, 54)
Step by step how the function works:
>>> date.utctimetuple()
time.struct_time(tm_year=2011, tm_mon=2, tm_mday=12, tm_hour=1, tm_min=33, tm_sec=54, tm_wday=5, tm_yday=43, tm_isdst=0)
>>> date.utctimetuple()[:6]
(2011, 2, 12, 1, 33, 54)
>>> datetime(*date.utctimetuple()[:6])
datetime.datetime(2011, 2, 12, 1, 33, 54)
In python3:
pip install python-dateutil
from dateutil.parser import tz
mydt.astimezone(tz.gettz('UTC')).replace(tzinfo=None)
from dateutil import tz
How about -
time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(seconds))
if seconds is None
then it converts the local time to UTC time else converts the passed in time to UTC.
Success story sharing
tzlocal.get_localzone()
to get the local timezone aspytz
tzinfo object