Python get local timezone offset in hours [duplicate] - python

In Python, how do you find what UTC time offset the computer is set to?

time.timezone:
import time
print -time.timezone
It prints UTC offset in seconds (to take into account Daylight Saving Time (DST) see time.altzone:
is_dst = time.daylight and time.localtime().tm_isdst > 0
utc_offset = - (time.altzone if is_dst else time.timezone)
where utc offset is defined via: "To get local time, add utc offset to utc time."
In Python 3.3+ there is tm_gmtoff attribute if underlying C library supports it:
utc_offset = time.localtime().tm_gmtoff
Note: time.daylight may give a wrong result in some edge cases.
tm_gmtoff is used automatically by datetime if it is available on Python 3.3+:
from datetime import datetime, timedelta, timezone
d = datetime.now(timezone.utc).astimezone()
utc_offset = d.utcoffset() // timedelta(seconds=1)
To get the current UTC offset in a way that workarounds the time.daylight issue and that works even if tm_gmtoff is not available, #jts's suggestion to substruct the local and UTC time can be used:
import time
from datetime import datetime
ts = time.time()
utc_offset = (datetime.fromtimestamp(ts) -
datetime.utcfromtimestamp(ts)).total_seconds()
To get UTC offset for past/future dates, pytz timezones could be used:
from datetime import datetime
from tzlocal import get_localzone # $ pip install tzlocal
tz = get_localzone() # local timezone
d = datetime.now(tz) # or some other local date
utc_offset = d.utcoffset().total_seconds()
It works during DST transitions, it works for past/future dates even if the local timezone had different UTC offset at the time e.g., Europe/Moscow timezone in 2010-2015 period.

gmtime() will return the UTC time and localtime() will return the local time so subtracting the two should give you the utc offset.
From https://pubs.opengroup.org/onlinepubs/009695399/functions/gmtime.html
The gmtime() function shall convert the time in seconds since the Epoch pointed to by timer into a broken-down time, expressed as Coordinated Universal Time (UTC).
So, despite the name gmttime, the function returns UTC.

I like:
>>> strftime('%z')
'-0700'
I tried JTS' answer first, but it gave me the wrong result. I'm in -0700 now, but it was saying I was in -0800. But I had to do some conversion before I could get something I could subtract, so maybe the answer was more incomplete than incorrect.

the time module has a timezone offset, given as an integer in "seconds west of UTC"
import time
time.timezone

You can use the datetime and dateutil libraries to get the offset as a timedelta object:
>>> from datetime import datetime
>>> from dateutil.tz import tzlocal
>>>
>>> # From a datetime object
>>> current_time = datetime.now(tzlocal())
>>> current_time.utcoffset()
datetime.timedelta(seconds=7200)
>>> current_time.dst()
datetime.timedelta(seconds=3600)
>>>
>>> # From a tzlocal object
>>> time_zone = tzlocal()
>>> time_zone.utcoffset(datetime.now())
datetime.timedelta(seconds=7200)
>>> time_zone.dst(datetime.now())
datetime.timedelta(seconds=3600)
>>>
>>> print('Your UTC offset is {:+g}'.format(current_time.utcoffset().total_seconds()/3600))
Your UTC offset is +2

hours_delta = (time.mktime(time.localtime()) - time.mktime(time.gmtime())) / 60 / 60

Create a Unix Timestamp with UTC Corrected Timezone
This simple function will make it easy for you to get the current time from a MySQL/PostgreSQL database date object.
def timestamp(date='2018-05-01'):
return int(time.mktime(
datetime.datetime.strptime( date, "%Y-%m-%d" ).timetuple()
)) + int(time.strftime('%z')) * 6 * 6
Example Output
>>> timestamp('2018-05-01')
1525132800
>>> timestamp('2018-06-01')
1527811200

Here is some python3 code with just datetime and time as imports. HTH
>>> from datetime import datetime
>>> import time
>>> def date2iso(thedate):
... strdate = thedate.strftime("%Y-%m-%dT%H:%M:%S")
... minute = (time.localtime().tm_gmtoff / 60) % 60
... hour = ((time.localtime().tm_gmtoff / 60) - minute) / 60
... utcoffset = "%.2d%.2d" %(hour, minute)
... if utcoffset[0] != '-':
... utcoffset = '+' + utcoffset
... return strdate + utcoffset
...
>>> date2iso(datetime.fromtimestamp(time.time()))
'2015-04-06T23:56:30-0400'

This works for me:
if time.daylight > 0:
return time.altzone
else:
return time.timezone

Related

Specify which timezone a datetime is in, in python

I have a datetime that i get from a database, this datetime is a UTC datetime. But when i pull it from the DB, it is unaware of the timezone. What i need to do, is convert this datetime to a "seconds from epoch" time for another function. The problem with this, is that the system's time is in PST and i am not able to change it for specific reasons.
So, what i want to do is, take this datetime that i get from the database, and tell python that this datetime is a UTC datetime. Every way that i have done that, results in it losing time or gaining time due to timezone conversions. Again, not trying to convert the time, just trying to specify that it is UTC.
If anyone can help with this that would be great.
Thanks!
Example
Assume database_function() returns a datetime data type that is '2013-06-01 01:06:18'
datetime = database_function()
epoch = datetime.strftime('%s')
pytz.utc.localize(database_function()).datetime.strftime('%s')
datetime.replace(tzinfo=pytz.utc).datetime.strftime('%s')
Both of these return a epoch timestamp of 1370077578
But, it SHOULD return a timestamp of 1370048778 per http://www.epochconverter.com/
Remember, this timestamp is a utc timestamp
Using the fabolous pytz:
import datetime, pytz
dt = datetime.datetime(...)
utc_dt = pytz.utc.localize(dt)
This creates a tz-aware datetime object, in UTC.
How about Setting timezone in Python This appears to reset the timezone within your python script. You are changing the time zone that your system sees given the specified time, not changing the specified time into the specified time zone. You probably want to set it to 'UTC'
time.tzset()
Resets the time conversion rules used by the library routines.
The environment variable TZ specifies how this is done.
New in version 2.3.
Availability: Unix.
I do not have this available on my home platform so I could not test it. I had to get this from the previous answer.
The answer marked best on the question is:
>>> import os, time
>>> time.strftime('%X %x %Z')
'12:45:20 08/19/09 CDT'
>>> os.environ['TZ'] = 'Europe/London'
>>> time.tzset()
>>> time.strftime('%X %x %Z')
'18:45:39 08/19/09 BST'
To get the specific values you've listed:
>>> year = time.strftime('%Y')
>>> month = time.strftime('%m')
>>> day = time.strftime('%d')
>>> hour = time.strftime('%H')
>>> minute = time.strftime('%M')
See here for a complete list of directives. Keep in mind that the strftime() function will always return a string, not an integer or other type.
You can Use pytz, which is a time zone definitions package.
from datetime import datetime
from pytz import timezone
fmt = "%Y-%m-%d %H:%M:%S %Z%z"
# Current time in UTC
now_utc = datetime.now(timezone('UTC'))
print now_utc.strftime(fmt)
# Convert to US/Pacific time zone
now_pacific = now_utc.astimezone(timezone('US/Pacific'))
print now_pacific.strftime(fmt)
# Convert to Europe/Berlin time zone
now_berlin = now_pacific.astimezone(timezone('Europe/Berlin'))
print now_berlin.strftime(fmt)
output:
2014-04-04 21:50:55 UTC+0000
2014-04-04 14:50:55 PDT-0700
2014-04-04 23:50:55 CEST+0200
or may be it helps
>> import pytz
>>> import datetime
>>>
>>> now_utc = datetime.datetime.utcnow() #Our UTC naive time from DB,
for the time being here I'm taking it as current system UTC time..
>>> now_utc
datetime.datetime(2011, 5, 9, 6, 36, 39, 883479) # UTC time in Naive
form.
>>>
>>> local_tz = pytz.timezone('Europe/Paris') #Our Local timezone, to
which we want to convert the UTC time.
>>>
>>> now_utc = pytz.utc.localize(now_utc) #Add Timezone information to
UTC time.
>>>
>>> now_utc
datetime.datetime(2011, 5, 9, 6, 36, 39, 883479, tzinfo=<UTC>) # The
full datetime tuple
>>>
>>> local_time = now_utc.astimezone(local\_tz) # Convert to local
time.
>>>
>>> local_time #Current local time in Paris
datetime.datetime(2011, 5, 9, 8, 36, 39, 883479, tzinfo=<DstTzInfo
'Europe/Paris' CEST+2:00:00 DST>)
Here is one way, using the pytz module:
import pytz
utc_datetime = (datetime.datetime(1970, 1, 1, tzinfo=pytz.utc)
+ datetime.timedelta(seconds=seconds_since_epoch)
If you don't want to install the pytz module, you can copy the example UTC class from the datetime documentation (search for "class UTC"):
https://docs.python.org/2/library/datetime.html#tzinfo-objects
Here's stdlib only solution without 3-party modules.
.., this datetime is a UTC datetime. But when i pull it from the DB, it is unaware of the timezone. What i need to do, is convert this datetime to a "seconds from epoch" time for another function.emphasize is mine
To convert an unaware (naive) datetime object that represents time in UTC to POSIX timestamp:
from datetime import datetime
timestamp = (dt_from_db - datetime(1970, 1, 1)).total_seconds()
Example:
>>> from datetime import datetime
>>> dt = datetime.strptime('2013-06-01 01:06:18', '%Y-%m-%d %H:%M:%S')
>>> (dt - datetime(1970, 1, 1)).total_seconds()
1370048778.0
See Converting datetime.date to UTC timestamp in Python that provides solutions for various Python versions.
To answer the question from the title: In general you need pytz library to handle timezones in Python. In particular, you should use .localize method to convert an unaware datetime object into timezone-aware one.
import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal
tz = get_localzone() # local timezone whatever it is (just an example)
aware_dt = tz.localize(naive_dt_in_local_timezone, is_dst=None)
is_dst=None asserts that naive_dt_in_local_timezone exists and unambiguous.
Though you don't need it for UTC timezone because it always has the same UTC offset (zero) around the year and in all past years:
import pytz
aware_dt = utc_dt.replace(tzinfo=pytz.utc)
See Python - simplest and most coherent way to get timezone-aware current time in UTC? (it provides a stdlib-only solution):
aware_dt = utc_dt.replace(tzinfo=timezone.utc)

Python date string manipulation based on timezone - DST

My objective is to take string(containg UTC date and time) as the input and convert it to local timezone based on Timezone difference. I have come up with the following code
Code
import time
print "Timezone Diff", time.timezone/3600
def convertTime(string):
print "Before Conversion"
print "year",string[0:4],"month",string[5:7],"day",string[8:10]
print "hour",string[11:13],"min",string[14:16]
print "After Conversion"
print "newhour",int(string[11:13])-(time.timezone/3600)
newhour = int(string[11:13])-(time.timezone/3600)
if newhour>=24:
print "year",string[0:4],"month",string[5:7],"newday",int(string[8:10])+1
print "hour",newhour-24,"min",string[14:16]
convertTime('2013:07:04:14:00')
Output:
Timezone Diff -10
Before Conversion
year 2013 month 07 day 04
hour 14 min 00
After Conversion
newhour 24
year 2013 month 07 newday 5
hour 0 min 00
This code is very basic , and clearly wouldn't work for month /year changes and not consider leap years. Can anyone suggest me a better approach to this issue.
Here's a solution with the datetime and pytz modules, using my timezone as an example:
import pytz
import datetime
s = '2013:07:04:14:00'
mydate = datetime.datetime.strptime(s, '%Y:%m:%d:%H:%M')
mydate = mydate.replace(tzinfo=timezone('Australia/Sydney'))
print mydate
Prints:
2013-07-04 14:00:00+10:00
You may have to "reshape" the code to work for your exact output, but I hope this helps in any way!
To convert UTC time to a local timezone using only stdlib, you could use an intermediate timestamp value:
from datetime import datetime
def convertTime(timestring):
utc_dt = datetime.strptime(timestring, '%Y:%m:%d:%H:%M')
timestamp = (utc_dt - datetime.utcfromtimestamp(0)).total_seconds()
return datetime.fromtimestamp(timestamp) # return datetime in local timezone
See How to convert a python utc datetime to a local datetime using only python standard library?.
To support past dates that have different utc offsets, you might need pytz, tzlocal libraries (stdlib-only solution works fine on Ubuntu; pytz-based solution should also enable Windows support):
from datetime import datetime
import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal
# get local timezone
local_tz = get_localzone()
def convertTime(timestring):
utc_dt = datetime.strptime(timestring, '%Y:%m:%d:%H:%M')
# return naive datetime object in local timezone
local_dt = utc_dt.replace(tzinfo=pytz.utc).astimezone(local_tz)
#NOTE: .normalize might be unnecessary
return local_tz.normalize(local_dt).replace(tzinfo=None)
The below piece of code sorted out the issue for me . Though pytz is probably the best approach to use. But in case you don't have pytz the below solution could be an alternative.
import datetime
def convertTime(timestring):
UTC_OFFSET_TIMEDELTA = datetime.datetime.utcnow() - datetime.datetime.now()
local_datetime = datetime.datetime.strptime(timestring, "%Y:%m:%d:%H:%M")
result_utc_datetime = local_datetime - UTC_OFFSET_TIMEDELTA
print result_utc_datetime.strftime("%Y-%m-%d %H:%M:%S"),
s = '2013:07:07:14:00'
convertTime(s)

Get new datetime object according to timezone difference

Here is my code
>>>from datetime import datetime
>>>from dateutil import tz
>>>current_time = datetime.utcnow().replace(tzinfo=tz.gettz('Asia/Calcutta'))
>>>2013-05-12 17:11:36.362000+05:30
i don't want offset-aware i want to add time difference to my current time
so the time will be
>>>2013-05-12 22:41:36.362000
so that i will be able to get time difference from by simply.
>>> datetime.utcnow() - current_time
Thanks,
You can obtain the offset with as a datetime.timedelta using:
offset = current_time.utcoffset()
The offset can then be added or subtracted from the current_time to obtain the desired datetime.
import datetime as DT
import dateutil.tz as tz
import dateutil
current_time = DT.datetime.utcnow().replace(tzinfo=tz.gettz('Asia/Calcutta'))
print(current_time)
# 2013-05-12 18:33:19.368122+05:30
offset = current_time.utcoffset()
naive_time = current_time.replace(tzinfo=None)
print(naive_time)
# 2013-05-12 18:33:19.368122
print(naive_time + offset)
# 2013-05-13 00:03:19.368122
Note that if you want the UTC time, you should subtract the offset:
print(naive_time - offset)
# 2013-05-12 13:03:19.368122
A simpler way to get the UTC datetime would be to use the astimezone method however:
utc = dateutil.tz.tzutc()
print(current_time.astimezone(utc))
# 2013-05-12 13:03:19.368122+00:00
Finally, note that using dateutil and replace to set the timezone does not always return the correct time. Here is how you could do it with pytz:
import pytz
calcutta = pytz.timezone('Asia/Calcutta')
utc = pytz.utc
current_time = calcutta.localize(DT.datetime.utcnow())
print(current_time)
# 2013-05-12 18:33:19.368705+05:30
print(current_time.astimezone(utc))
# 2013-05-12 13:03:19.368705+00:00
You can get the offset by using datetime.utcoffset()
current_time = datetime.utcnow().replace(tzinfo=tz.gettz('Asia/Calcutta'))
td = datetime.utcoffset(current_time)
#datetime.timedelta(0, 19800)
td.total_seconds() / 3600
#5.5

From a timezone and a UTC time, get the difference in seconds vs local time at that point in time

This should be very simple, but I can't quite figure it out in Python.
I want to have a function which takes two arguments, a UTC time in seconds and a zoneinfo name like 'Europe/Vienna' and returns the offset in seconds from local time and UTC for that point in time.
In C it would be:
/* ... code to to set local time to the time zone I want to compare against,
not shown here. Then call function below to get difference vs localtime.
Hardly an ideal solution,
but just to demonstrate what I want in a "lingua franca" (C): */
int get_diff_vs_localtime(const time_t original_utc_time)
{
struct tm* ts;
ts = localtime(&original_utc_time);
return mktime(ts) - original_utc_time;
}
I guess my question really boils down to: "given an Olson timezone (example 'Europe/Stockholm') and a UTC time, what is the local time?
Assuming "UTC time in seconds" means POSIX timestamp. To convert it to Stockholm time:
from datetime import datetime
import pytz
tz = pytz.timezone('Europe/Stockholm')
utc_dt = datetime.utcfromtimestamp(posix_timestamp).replace(tzinfo=pytz.utc)
dt = tz.normalize(utc_dt.astimezone(tz))
print(dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'))
tz.normalize() is unnecessary if the source timezone is UTC (like in this case).
A simpler alternative is to use fromtimestamp()'s tz parameter, to convert "seconds since the epoch" to local time:
from datetime import datetime
import pytz
tz = pytz.timezone('Europe/Stockholm')
dt = datetime.fromtimestamp(posix_timestamp, tz)
print(dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'))
Both examples produce the same result.
If local machine uses "right" timezones then to convert POSIX timestamp received from an external source to UTC, an explicit formula could be used:
from datetime import datetime, timedelta
import pytz
utc_dt = datetime(1970, 1, 1, tzinfo=pytz.utc) + timedelta(seconds=posix_timestamp)
The latest formula may also support a larger date range (less likely issues with dates before 1970, after 2038 or 3000 years).
If the timestamp comes from the local "right" source then the first two examples should be used instead (they call "right" time.gmtime()).
You could use pytz and datetime to do something in the manner of:
from datetime import datetime
from pytz import timezone
def get_diff(now, tzname):
tz = timezone(tzname)
utc = timezone('UTC')
utc.localize(datetime.now())
delta = utc.localize(now) - tz.localize(now)
return delta
Which for the following example...
now = datetime.utcnow()
print(now)
tzname = 'Europe/Stockholm'
delta = get_diff(now, tzname)
print(delta)
now_in_stockholm = now + delta
print(now_in_stockholm)
... outputs:
2012-10-02 14:38:56.547475
2:00:00
2012-10-02 16:38:56.547475
This is pretty old, but I couldn't find a great answer, so here's what I came up with:
from datetime import datetime
local = datetime.now()
utc = datetime.utcnow()
int((local - utc).days * 86400 + round((local - utc).seconds, -1))
Returns:
-21600
because I am (currently) 21600 seconds (6 hours) behind UTC.
Note: the second date calculated (in this case UTC) needs to be rounded since there is a super small difference in time at each calculation.
I guess my question really boils down to: "given an Olson timezone
(example 'Europe/Stockholm') and a UTC time, what is the local time?
If I understand your problem correctly:
from pytz import timezone
import datetime, time
tz = timezone('Asia/Kuwait')
utc_dt = datetime.datetime.utcfromtimestamp(time.time())
utc_dt + tz.utcoffset(utc_dt)
>>> tz.utcoffset(utc_dt).seconds
10800
>>> tz
<DstTzInfo 'Asia/Kuwait' LMT+3:12:00 STD>
>>> utc_dt + tz.utcoffset(utc_dt)
datetime.datetime(2012, 10, 2, 17, 13, 53, 504322)
>>> utc_dt
datetime.datetime(2012, 10, 2, 14, 13, 53, 504322)

Getting computer's UTC offset in Python

In Python, how do you find what UTC time offset the computer is set to?
time.timezone:
import time
print -time.timezone
It prints UTC offset in seconds (to take into account Daylight Saving Time (DST) see time.altzone:
is_dst = time.daylight and time.localtime().tm_isdst > 0
utc_offset = - (time.altzone if is_dst else time.timezone)
where utc offset is defined via: "To get local time, add utc offset to utc time."
In Python 3.3+ there is tm_gmtoff attribute if underlying C library supports it:
utc_offset = time.localtime().tm_gmtoff
Note: time.daylight may give a wrong result in some edge cases.
tm_gmtoff is used automatically by datetime if it is available on Python 3.3+:
from datetime import datetime, timedelta, timezone
d = datetime.now(timezone.utc).astimezone()
utc_offset = d.utcoffset() // timedelta(seconds=1)
To get the current UTC offset in a way that workarounds the time.daylight issue and that works even if tm_gmtoff is not available, #jts's suggestion to substruct the local and UTC time can be used:
import time
from datetime import datetime
ts = time.time()
utc_offset = (datetime.fromtimestamp(ts) -
datetime.utcfromtimestamp(ts)).total_seconds()
To get UTC offset for past/future dates, pytz timezones could be used:
from datetime import datetime
from tzlocal import get_localzone # $ pip install tzlocal
tz = get_localzone() # local timezone
d = datetime.now(tz) # or some other local date
utc_offset = d.utcoffset().total_seconds()
It works during DST transitions, it works for past/future dates even if the local timezone had different UTC offset at the time e.g., Europe/Moscow timezone in 2010-2015 period.
gmtime() will return the UTC time and localtime() will return the local time so subtracting the two should give you the utc offset.
From https://pubs.opengroup.org/onlinepubs/009695399/functions/gmtime.html
The gmtime() function shall convert the time in seconds since the Epoch pointed to by timer into a broken-down time, expressed as Coordinated Universal Time (UTC).
So, despite the name gmttime, the function returns UTC.
I like:
>>> strftime('%z')
'-0700'
I tried JTS' answer first, but it gave me the wrong result. I'm in -0700 now, but it was saying I was in -0800. But I had to do some conversion before I could get something I could subtract, so maybe the answer was more incomplete than incorrect.
the time module has a timezone offset, given as an integer in "seconds west of UTC"
import time
time.timezone
You can use the datetime and dateutil libraries to get the offset as a timedelta object:
>>> from datetime import datetime
>>> from dateutil.tz import tzlocal
>>>
>>> # From a datetime object
>>> current_time = datetime.now(tzlocal())
>>> current_time.utcoffset()
datetime.timedelta(seconds=7200)
>>> current_time.dst()
datetime.timedelta(seconds=3600)
>>>
>>> # From a tzlocal object
>>> time_zone = tzlocal()
>>> time_zone.utcoffset(datetime.now())
datetime.timedelta(seconds=7200)
>>> time_zone.dst(datetime.now())
datetime.timedelta(seconds=3600)
>>>
>>> print('Your UTC offset is {:+g}'.format(current_time.utcoffset().total_seconds()/3600))
Your UTC offset is +2
hours_delta = (time.mktime(time.localtime()) - time.mktime(time.gmtime())) / 60 / 60
Create a Unix Timestamp with UTC Corrected Timezone
This simple function will make it easy for you to get the current time from a MySQL/PostgreSQL database date object.
def timestamp(date='2018-05-01'):
return int(time.mktime(
datetime.datetime.strptime( date, "%Y-%m-%d" ).timetuple()
)) + int(time.strftime('%z')) * 6 * 6
Example Output
>>> timestamp('2018-05-01')
1525132800
>>> timestamp('2018-06-01')
1527811200
Here is some python3 code with just datetime and time as imports. HTH
>>> from datetime import datetime
>>> import time
>>> def date2iso(thedate):
... strdate = thedate.strftime("%Y-%m-%dT%H:%M:%S")
... minute = (time.localtime().tm_gmtoff / 60) % 60
... hour = ((time.localtime().tm_gmtoff / 60) - minute) / 60
... utcoffset = "%.2d%.2d" %(hour, minute)
... if utcoffset[0] != '-':
... utcoffset = '+' + utcoffset
... return strdate + utcoffset
...
>>> date2iso(datetime.fromtimestamp(time.time()))
'2015-04-06T23:56:30-0400'
This works for me:
if time.daylight > 0:
return time.altzone
else:
return time.timezone

Categories