I need to know the current time at CDT when my Python script is run. However this script will be run in multiple different timezones so a simple offset won't work.
I only need a solution for Linux, but a cross platform solution would be ideal.
pytz or dateutil.tz is the trick here. Basically it's something like this:
>>> from pytz import timezone
>>> mytz = timezone('Europe/Paris')
>>> yourtz = timezone('US/Eastern')
>>> from datetime import datetime
>>> now = datetime.now(mytz)
>>> alsonow = now.astimezone(yourtz)
The difficulty actually lies in figuring out which timezone you are in. dateutil.tz is better at that.
>>> from dateutil.tz import tzlocal, gettz
>>> mytz = tzlocal()
>>> yourtz = gettz('US/Eastern')
If you want all the nitty gritty details of why timezones are evil, they are here:
http://regebro.wordpress.com/2007/12/18/python-and-time-zones-fighting-the-beast/
http://regebro.wordpress.com/2008/05/10/python-and-time-zones-part-2-the-beast-returns/
http://regebro.wordpress.com/2008/05/13/thanks-for-the-testing-help-conclusions/
You can use time.gmtime() to get time GMT (UTC) from any machine no matter the timezone, then you can apply your offset.
A simple offset will work, you just need to offset from UTC.
Using datetime you can get the current utc (gmt) time and use datetime objects:
datetime.datetime.utcnow() - Provides time at UTC
datetime.datetime.now() - Provides time at local machine
To get the CT time from any system you need to know the CT time offset from UTC.
Then to account for daylight savings time code a function to get the current offset.
>>> import datetime
>>> utc = datetime.datetime.utcnow()
>>> current_ct_offset = get_current_ct_offset()
>>> ct_datetime = utc + datetime.timedelta(hours=current_ct_offset)
I could be overlooking something here, but if your only concerned about one timezone and your not doing tz name handling, it's pretty straight forward.
Related
Maybe someone came across and will be able to give advise.
I am getting the time zone "Europe / Moscow", but it needs to be converted to "UTC + 3".
Only an idea with a dictionary comes to mind, but this is rather a last resort.
I would not be surprised if there are ready-made solutions, but I did not google it well)
Example:
timezone = "Europe/Moscow" -> timezone = "UTC+3"
Python 3.9+:
You can use the zoneinfo package. (link)
Make sure to consider daylight saving time.
from datetime import datetime
import zoneinfo
zone = zoneinfo.ZoneInfo("Europe/Moscow")
offset = datetime.now(zone).utcoffset().total_seconds()//(60*60)
print(offset) # 3 / 4 - This depends on daylight saving time
print(f"UTC+{int(offset)}") # UTC+3 / UTC+4
Older:
Try pytz, but make sure to consider daylight saving time. (link)
import pytz
from datetime import datetime
moscow_tz = pytz.timezone("Europe/Moscow")
offset = moscow_tz.utcoffset(datetime.now())
print(offset) # 3:00:00 / 4:00:00 - This depends on daylight saving time
print(f"UTC+{int(offset.total_seconds()//(60*60))}") # UTC+3 / UTC+4
so I'm trying to make a discord bot in python and make a command that will display all timezones that I choose, but the problem is that all of these timezones are around 7-8 hours ahead of normal.
import datetime
from pytz import timezone
localFormat = "%Y-%m-%d %H:%M:%S, %Z%z"
UTC=datetime.datetime.utcnow()
timezonelist = ["US/Eastern", "US/Central", "US/Mountain", "US/Pacific", "Etc/UTC", "Europe/Berlin", "Australia/North", "Australia/South", "Australia/West"]
for tz in timezonelist:
localDatetime = UTC.astimezone(timezone(tz))
x = localDatetime.strftime(localFormat)
print(tz + " " + x)
for example, Etc/UTC outputs 05:56:25 when it should output 22:56:25, other timezones follow this example, EST outputs 00:56:25 when it should be 17:56:25, or MST (where I am), 22:56:25 instead of 15:56:25. However, datetime.utcnow() returns the correct time.
I had done some research and it said that PYTZ uses the LMT but since all are forward by an amount I do not think it has to do with that.
utcnow() gives you a naive datetime object - it is not aware that it's in UTC although the numbers show UTC. If you convert to another time zone, Python will assume all naive datetime objects are local time. Your local time (MST) is UTC-7, that's why you're off by 7 hours.
The behaviour of utcnow is confusing and can lead to unexpected results - Stop using utcnow and utcfromtimestamp. Instead, use now() and set the tz explicitly:
UTC = datetime.datetime.now(timezone('UTC'))
Can someone explain me why I do not get the same result in those?
import datetime,pytz
var1 = datetime.datetime(2017,10,25,20,10,50,tzinfo=pytz.timezone("Europe/Athens")))
print(var1)
The output of this code is: 2017-10-25 20:10:50+01:35
import datetime,pytz
var1 = datetime.datetime(2017,10,25,20,10,50)
var1 = pytz.timezone("Europe/Athens").localize(var1)
print(var1)
The output of this code is: 2017-10-25 20:10:50+03:00
My question is why they have different timezones (1:35 and 3:00). I know that the second code is true because my UTC is 3:00. But can you tell me why I am getting 1:35 in the first one?
There is no problem, datetime just happily reports the offset of the tzinfo in whatever reference frame.
By default pytz.timezone doesn't give the UTC offset but the LMT (local mean time) offset:
>>> pytz.timezone("Europe/Athens")
<DstTzInfo 'Europe/Athens' LMT+1:35:00 STD>
# ^^^-------------------- local mean time
However when you localize it:
>>> var1 = datetime.datetime(2017,10,25,20,10,50)
>>> var1 = pytz.timezone("Europe/Athens").localize(var1)
>>> var1.tzinfo
<DstTzInfo 'Europe/Athens' EEST+3:00:00 DST>
# ^^^^-------------------- eastern european summer time
A different offset is now reported, this time based on the EEST.
tzinfo doesn't work well for some timezones and that could be the reason for the wrong result.
pytz doc:
Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones.
Using localize or astimezone is a fix to this problem. Doc says that The preferred way of dealing with times is to always work in UTC, converting to localtime only when generating output to be read by humans.
import datetime, pytz
localTimezone = pytz.timezone('Europe/Athens')
var1 = datetime.datetime(2017,10,25,20,10,50,tzinfo=pytz.utc)
loc_dt = var1.astimezone(localTimezone)
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
print(loc_dt.strftime(fmt))
This will print
2017-10-25 23:10:50 EEST+0300
In the second code, you use .localize(), which takes a naive datetime object and interprets it as if it is in that timezone. It does not move the time to another timezone. A naive datetime object has no timezone information to be able to make that move possible.
As you are making the time local in the second code, the time shown in the second one is correct. As you are not making the time local in the first code, the time shown is incorrect.
i have timestamps in the following format:
2011 February 2nd 13h 27min 21s
110202 132721
I want to convert 110202 132721 into the corresponding linux timestamp: 1296682041
Is there any quick efficient way to achieve this?
Something like
>>> s = "110202 132721"
>>> print time.mktime(time.strptime(s, "%y%m%d %H%M%S"))
1296653241.0
This interprets the time as a local time (your current time zone).
To create a Unix timestamp, use the time.mktime(t) function. It takes a time.struct_time object.
The objects definition can be viewed here. So you just have to parse the date and the time and put it into the object before handing it over to the mktime() function
Without your timezone information, this is not the 'corresponding' unix timestamp.
After a few attempts I have guessed you could be located in the Pacific coast of USA, so you have to define it explicitely in your script:
from datetime import datetime
import pytz
import calendar
a = "110202 132721"
yourTZ = 'America/Los_Angeles'
calendar.timegm(pytz.timezone(yourTZ).localize(datetime.strptime(a, '%y%m%d %H%M%S')).utctimetuple())
# returns 1296682041
In a Python project I'm working on, I'd like to be able to get a "human-readable" timezone name of the form America/New_York, corresponding to the system local timezone, to display to the user. Every piece of code I've seen that accesses timezone information only returns either a numeric offset (-0400) or a letter code (EDT) or sometimes both. Is there some Python library that can access this information, or if not that, convert the offset/letter code into a human-readable name?
If there's more than one human-readable name corresponding to a particular timezone, either a list of the possible results or any one of them is fine, and if there is no human-readable name corresponding to the current time zone, I'll take either an exception or None or [] or whatever.
A clarification: I don't remember exactly what I had in mind when I originally wrote this question, but I think what I really wanted was a way to turn a timezone into a human-readable name. I don't think this question was meant to focus on how to get the system local timezone specifically, but for the specific use case I had in mind, it just happened that the local timezone was the one I wanted the name for. I'm not editing the bit about the local timezone out of the question because there are answers focusing on both aspects.
The following generates a defaultdict mapping timezone offsets (e.g. '-0400') and abbreviations (e.g. 'EDT') to common geographic timezone names (e.g. 'America/New_York').
import os
import dateutil.tz as dtz
import pytz
import datetime as dt
import collections
result = collections.defaultdict(list)
for name in pytz.common_timezones:
timezone = dtz.gettz(name)
now = dt.datetime.now(timezone)
offset = now.strftime('%z')
abbrev = now.strftime('%Z')
result[offset].append(name)
result[abbrev].append(name)
for k, v in result.items():
print(k, v)
Note that timezone abbreviations can have vastly different meanings. For example, 'EST' could stand for Eastern Summer Time (UTC+10) in Australia, or Eastern Standard Time (UTC-5) in North America.
Also, the offsets and abbreviations may change for regions that use daylight standard time. So saving the static dict may not provide the correct timezone name 365 days a year.
I'd like to be able to get a "human-readable" timezone name of the form America/New_York, corresponding to the system local timezone, to display to the user.
There is tzlocal module that returns a pytz tzinfo object (before tzlocal 3.0 version) that corresponds to the system local timezone:
#!/usr/bin/env python
import tzlocal # $ pip install tzlocal
# display "human-readable" name (tzid)
print(tzlocal.get_localzone_name())
# Example Results:
# -> Europe/Moscow
# -> America/Chicago
To answer the question in the title (for people from google), you could use %Z%z to print the local time zone info:
#!/usr/bin/env python
import time
print(time.strftime('%Z%z'))
# Example Results:
# -> MSK+0300
# -> CDT-0500
It prints the current timezone abbreviation and the utc offset corresponding to your local timezone.
http://pytz.sourceforge.net/ may be of help. If nothing else, you may be able to grab a list of all of the timezones and then iterate through until you find one that matches your offset.
This may not have been around when this question was originally written, but here is a snippet to get the time zone official designation:
>>> eastern = timezone('US/Eastern')
>>> eastern.zone
'US/Eastern'
Further, this can be used with a non-naive datetime object (aka a datetime where the actual timezone has been set using pytz.<timezone>.localize(<datetime_object>) or datetime_object.astimezone(pytz.<timezone>) as follows:
>>> import datetime, pytz
>>> todaynow = datetime.datetime.now(tz=pytz.timezone('US/Hawaii'))
>>> todaynow.tzinfo # turned into a string, it can be split/parsed
<DstTzInfo 'US/Hawaii' HST-1 day, 14:00:00 STD>
>>> todaynow.strftime("%Z")
'HST'
>>> todaynow.tzinfo.zone
'US/Hawaii'
This is, of course, for the edification of those search engine users who landed here. ... See more at the pytz module site.
If you want only literally what you asked for, "the timezone name of the form America/New_York, corresponding to the system local timezone", and if you only care about Linux (and similar), then this should do the job:
import os
import os.path
import sys
def main(argv):
tzname = os.environ.get('TZ')
if tzname:
print tzname
elif os.path.exists('/etc/timezone'):
print file('/etc/timezone').read()
else:
sys.exit(1)
if __name__ == '__main__':
main(sys.argv)
Of course it would be nicer to have a library that encapsulates this in a cleaner way, and that perhaps handles the other cases you mention in comments like already having a tzinfo object. I think you can do that with pytz mentioned by Amber but it's not obvious to me just how...
Check out python-dateutil
py> from dateutil.tz import *
py> ny = gettz('America/New York')
py> ny._filename
'/usr/share/zoneinfo/America/New_York'
py> ny._filename.split('/', 4)[-1]
'America/New_York'
# use tzlocal library
from tzlocal import get_localzone
current_timezone = get_localzone()
zone = current_timezone.zone
print(zone)
Working with the latest version of tzlocal which is 4.1 as of today, tzlocal.get_localzone().key produces the following error: AttributeError: '_PytzShimTimezone' object has no attribute 'key'. But tzlocal.get_localzone().zone works lovely.