Python Time zone: get abbreviation and UTC offset - python-3.x

my time zone is "Australia/Melbourne" (I have multiple zones like this when I give this to my function) and I need the output like this ASET(GMT +10). How can I reach my answer?
Thank you

assuming you have date and time available (see my comment), the easiest way is probably strftime:
from datetime import datetime
from dateutil import tz
timezone = tz.gettz("Australia/Melbourne")
dt = datetime.now(timezone)
print(f"{dt.strftime('%Z')}(GMT{dt.strftime('%z')})")
# AEST(GMT+1000)
If you exactly want to get the specified output, I suppose you have to go a little more sophisticated:
total_minutes, seconds = divmod(dt.utcoffset().total_seconds(), 60)
hours, minutes = divmod(total_minutes, 60)
utcoff = f"{int(hours):+d}:{int(minutes):02d}" if minutes else f"{int(hours):+d}"
print(f"{dt.strftime('%Z')}(GMT{utcoff})")
# AEST(GMT+10)

Related

Subtracting time format variables

I have a variable assigned as start time and want to subtract the same with current system time inorder to calculate total ours.
eg:
from datetime import datetime
start = "9:45:00"
total_hours = start - datetime.now().strftime("%H:%M:%S")
is this a correct approach?

Parse string like "15 mins" or "1hr 10mins" to seconds

Does anyone know where I can find a good function that converts a string like "15 mins" or "1hr 20mins" into an integer denoting the number of seconds?
I think you can find your solution here , and you can write your own function which does this, by writing a formal way to parse your time, you can transform your string into a datetime and the rest is straight forward.
from datetime import datetime, timedelta
# we specify the input and the format...
t = datetime.strptime("05:20:25","%H:%M:%S")
# ...and use datetime's hour, min and sec properties to build a timedelta
delta = timedelta(hours=t.hour, minutes=t.minute, seconds=t.second)
print(delta)
assert(5*60*60+20*60+25 == delta.total_seconds())

How to create a Timezone aware Time object that works with all dates?

I have been struggling with this issue for a while now. I feel that I understand Timezones well, and I think I understand how to use pytz properly so I usually use that and I typically don't have any problems. Maybe I am trying to use the wrong tools for what I want.
With my current application, I need to work in abstract time objects. That is, I care about something that happens at 16:00. I don't care that it happens at 16:00 ON December 23rd. It seems that pytz prefers working with datetime objects: and that makes sense. It can't figure out the offset since it's different based on the day for daylight savings and historical reasons and so on.
I'm trying to allow users to coordinate daily events all around the world. If a user in Japan says the event is from 21:00 to 23:00 every day, I want users in US/Central to see 6:00 to 8:00 every day. And I thought I had this working... until two weeks ago that is. See, DST just ended in most of the United States, so what now is 6:00-8:00 was actually previously 7:00-9:00.
This breaks my idea that I need to typically store times in UTC, then convert them only for viewing. The timezone it was created in is actually very important. If we reverse this, and a user in a US time zone that observes Daylight Savings sets an event time, that time needs to change in Japan even though they don't observe it! If I store that time as UTC, nothing changes in Japan, but that is not the functionality I want.
So I would like to store as a time object with tzinfo. But you can't create a time object with an accurate pytz tzinfo without a date, but the date isn't important. If I use the current date to figure out the tzinfo then that will actually cease to be accurate once that time zone changes.
I guess my question is: what the best way to store "4 PM Eastern" in a way that can be retrieved anywhere in the world, at any time in the future? That includes Eastern! I want it to be 4PM during DST and also outside of DST. I can't store it as UTC, because 12:00 UTC is the same time as 12:00 UTC during the entire year, but I don't want that. What I think I want is, an "abstract" or "temporary" pytz.timezone that doesn't have an actual offset until the date (the date of viewing) is given. Is that a thing? I've read countless questions on this site, both the python and pytz docs, and can't find anything like this, or anyone with a similar problem. Everything seems to talk about specific datetimes or working only within datetimes but that doesn't seem relevant to my issue.
My application is pretty huge so it's hard to pull out the specific parts, but I can try to show what I've tried and why things don't work.
event_time = datetime.time(hour=12, tzinfo=pytz.timezone("US/Eastern")) would be my ideal solution. But using pytz for tzinfo creation is not a good idea (this will give me an offset like -5:04 because of historical reasons) - is there a way to specify the version of US/Eastern to use?
datetime.now(pytz.timezone("US/Eastern")).replace(hour=12, minute=0, second=0, microsecond=0).timetz() gives me something that looks like what I want, but it only functions correctly as long as US/Eastern doesn't change. If I apply this to a date that I have moved back before the DST change, it gives me 13:00, which is not what I want.
I built a tzinfo class that automatically handles the conversion of DST. I got the idea from the USTimeZone class example in the datetime documentation.
The trick here is the pytz timezone database has all the historical dates of when daylight savings goes into effect. That's also why when you create a datetime object without a date, it converts the DST incorrectly; it's going based off the first entry in the database.
from datetime import datetime, tzinfo, timedelta
import pytz
ZERO = timedelta(0)
def format_timedelta(td):
if td < timedelta(0):
return '-' + format_timedelta(-td)
else:
# Change this to format positive timedeltas the way you want
return str(td)
class WorldTimeZone(tzinfo):
"""
A self adjusting according to DST rules in the PYTZ database tzinfo class
See pytz.all_timezones for a list of all zone names and offsets.
"""
def __init__(self, zone):
"""
:param zone: (str) Proper tzdatabase timze zone name.
"""
# initialize the pytz timezone with current time
# this is done to avoid confusing tznames found in the start of the tz database
# _utcoffset should always be STD rather than DST.
self.pytzinfo = self.__getSTD(zone)
self._utcoffset = self.pytzinfo._utcoffset
#staticmethod
def __getSTD(tname):
"""
This returns a pytz timezone object normalized to standard time for the zone requested.
If the zone does not follow DST or a future transition time cannot be found, it normalizes to NOW instead.
:param tname: Proper timezone name found in the tzdatabase. example: "US/Central"
"""
# This defaults to the STD time for the zone rather than current time which could be DST
tzone = pytz.timezone(tname)
NOW = datetime.now(tz=pytz.UTC)
std_date = NOW
hasdst = False
try:
#transitions are in UTC. They need to be converted to localtime once we find the correct STD transition.
for utcdate, info in zip(tzone._utc_transition_times, tzone._transition_info):
utcdate = utcdate.replace(tzinfo=pytz.UTC)
utcoffset, dstoffset, tzname = info
if dstoffset == ZERO:
std_date = utcdate
if utcdate > NOW:
hasdst = True
break
except AttributeError:
std_date = NOW
if not hasdst:
std_date = NOW
std_date = tzone.normalize(std_date)
return std_date.tzinfo
# This needs to be dynamic because pytzinfo updates everytime .dst() is called; which is a lot.
#property
def _dst(self):
return self.pytzinfo._dst
def __repr__(self):
# return self.pytzinfo.__repr__()
if self._dst:
dst = 'DST'
else:
dst = 'STD'
if self._utcoffset > timedelta(seconds=0):
msg = '<WorldTimeZone %r %s+%s %s>'
else:
msg = '<WorldTimeZone %r %s%s %s>'
return msg % (self.pytzinfo.zone, self.pytzinfo._tzname,
format_timedelta(self._utcoffset + self._dst), dst)
def __str__(self):
return "%s %s" % (self.pytzinfo._tzname, self.pytzinfo)
def tzname(self, dt):
# print " TZNAME called"
return "%s %s" % (self.pytzinfo._tzname, self.pytzinfo)
def utcoffset(self, dt):
# print " UTCOFFSET CALLED"
return self._utcoffset + self.dst(dt)
def dst(self, dt):
# print " DST CALLED"
if dt is None or dt.tzinfo is None:
# An exception may be sensible here, in one or both cases.
# It depends on how you want to treat them. The default
# fromutc() implementation (called by the default astimezone()
# implementation) passes a datetime with dt.tzinfo is self.
return ZERO
assert dt.tzinfo is self # WE ASSUME THE TZINFO ON THE DATE PASSED IN IS OUR TZINFO OBJECT.
tmpdt = self.pytzinfo.normalize(dt)
self.pytzinfo = tmpdt.tzinfo
return tmpdt.tzinfo._dst
Sample code
EST = WorldTimeZone('US/Eastern')
PST = WorldTimeZone('US/Pacific')
dt_dst = datetime(2018, 11, 1, 1, 30, 00)
dt_std = datetime(2018, 11, 6, 1, 30, 00)
est_dst = dt_dst.replace(tzinfo=EST)
est_std = dt_std.replace(tzinfo=EST)
pst_dst = est_dst.astimezone(PST)
pst_std = est_std.astimezone(PST)
print(f"{dt_dst} >> {est_dst} >> {pst_dst}")
print(f"{dt_std} >> {est_std} >> {pst_std}")
outputs
2018-11-01 01:30:00 >> 2018-11-01 01:30:00-04:00 >> 2018-10-31 22:30:00-07:00
2018-11-06 01:30:00 >> 2018-11-06 01:30:00-05:00 >> 2018-11-05 22:30:00-08:00
It looks like pytz provides this through the 'localize' method, as suggested in `this answer.
From the pytz documentation:
If you insist on working with local times, this library provides a facility for constructing them unambiguously:
eastern = timezone('US/Eastern')
loc_dt = datetime(2002, 10, 27, 1, 30, 00)
est_dt = eastern.localize(loc_dt, is_dst=True)
edt_dt = eastern.localize(loc_dt, is_dst=False)
print(est_dt.strftime(fmt) + ' / ' + edt_dt.strftime(fmt))
2002-10-27 01:30:00 EDT-0400 / 2002-10-27 01:30:00 EST-0500`
By storing the local time, and the local time zone, you can then convert it when you use it, and convert it to another region's time zone.

Time data from API convert to Date time python

i have this problem with milliseconds or microseconds data from api im not totally sure. I am trying to convert this to a readable date time. below is an example. The web app has a dashboard which you i can check the date time. but i do not know exactly how to convert it to a readable date time.
Example 1:
FROM API
"start":1542243678,
FROM Dashboard
11/15/2018 9:01 am
Example 2:
FROM API
"end":1542330078,
FROM Dashboard
11/16/2018 9:01 am
When i try to convert to python date time it gives me wrong info.
import datetime
import time
milliseconds = 1542243678
date = datetime.datetime.fromtimestamp(milliseconds/1000.0)
date = date.strftime('%Y-%m-%d %H:%M:%S')
print(date)
Output:
1970-01-19 04:24:03
Sorry if I don't understand your question correctly, but is this what you want?
import datetime
import time
milliseconds = 1542243678
date = datetime.datetime.fromtimestamp(milliseconds)
date = date.strftime('%m/%d/%Y %I:%M %p')
print(date)
Output: 11/14/2018 05:01 PM
You don't need to divide by 1000 before passing to datetime.datetime.fromtimestamp.
Try datetime.datetime.fromtimestamp(1542243678). It should work.

Setting Loop with start and end date

Thats a code a friend of mine helped me with in order to get files from diferent measurement systems, timestamps and layout into on .csv file.
You enter the timeperiod or like in the case below 1 day and the code looks for this timestamps in different files and folders, adjusts timestamps (different Timezone etc.) and puts everything into one .csv file easy to plot. Now I need to rewrite that stuff for different layouts. I managed to get everything working but now I don't want to enter every single day manually into the code :-( , cause I'd need to enter it 3 times in a row --> in order to get the day for one day into one file, dateFrom and dateTo needs to be the same and in the writecsv...section you'd have to enter the date again.
here's the code:
from importer import cloudIndices, weatherall, writecsv,averagesolar
from datetime import datetime
from datetime import timedelta
dateFrom = datetime.strptime("2010-06-21", '%Y-%m-%d')
dateTo = datetime.strptime("2010-06-21", '%Y-%m-%d')
....
code
code
....
writecsv.writefile("data_20100621", header, ciData)
what can I change here so that I get an automatic loop for all data between e.g 2010-06-21 to 2011-06-21
p.s. if i'd entered 2010-06-21in dataFromand 2011-06-21 in dateTo i'd get a huge cvs. file with all the data in it ..... I thought that would be a great idea but it's not really good for plotting so I enden up manually entering day after day which isn't bad if you do it on a regular basis for 2 or 3 days but now a dates showed up and I need to rund the code over it :-(
Generally speaking you should be using datetime.datetime and datetime.timedelta, here is an example of how:
from datetime import datetime
from datetime import timedelta
# advance 5 days at a time
delta = timedelta(days=5)
start = datetime(year=1970, month=1, day=1)
end = datetime(year=1970, month=2, day=13)
print("Starting from: %s" % str(start))
while start < end:
print("advanced to: %s" % str(start))
start += delta
print("Finished at: %s" % str(start))
This little snippet creates a start and end time and a delta to advance using the tools python provides. You can modify it to fit your needs or apply it in your logic.

Resources