I'm working on backend ,Short Explanation :
I have 2 timestamps which are in this format "2022-10-29T16:30:00+05:30","2022-10-29T17:30:00+05:30" .I need to calculate this duration between these but I tried to figure out the format of this timestamp,so I could calculate using datetime method in python.
This uses the method datetime.fromisoformat(date_string) to convert the ISO 8601-formatted string into a datetime object. From there, you can subtract to find the time difference. Additionally, you may want to add some code to check for negative results, or you can simply use the function abs(x).
import datetime
def duration_between(ts_1: str, ts_2: str) -> datetime.datetime:
ts_1_dt = datetime.datetime.fromisoformat(ts_1)
ts_2_dt = datetime.datetime.fromisoformat(ts_2)
return ts_2_dt - ts_1_dt
ts_1 = "2022-10-29T16:30:00+05:30"
ts_2 = "2022-10-29T17:30:00+05:30"
delta: datetime.datetime = duration_between(ts_1, ts_2)
print(delta) # 1:00:00
print(delta.total_seconds()) # 3600.0
To obtain the delta in other common formats (years, days, hours, minutes, seconds, microseconds), see this answer: https://stackoverflow.com/a/47207182/11597788
I need to specify a parameter to a python script indicating time back from now. For example 1d is 1 day from now, 2h is 2 hours from now, 2d3h is 2 days, 3 hours from now. Similar to the journalctl --vacuum-time format (reference).
For example, this script will collect the data between now and 2 days and 3 hours in the past:
collect_data_script.py --start=2d3h
Is there some standard way to handle this parameter and a package that can process this time format? Or I will have to write it from scratch?
The ISO 8601 duration format like 2DT3H for "2 days (time designator) 3 hours" can be parsed using module isodate from Gerhard Weiss:
implements ISO 8601 date, time and duration parsing. The implementation follows ISO8601:2004 standard
parse_duration:
parses an ISO 8601 duration string into a timedelta or Duration object.
Example:
import isodate
isodate.parse_duration('p2d3h'.upper()) # prefix with 'p' for period and to uppercase
# will raise ValueError because ISO 8601 time designator 'T' missing
timedelta = isodate.parse_duration('p2dt3h'.upper()) # insert 'T' to work
# datetime.timedelta(2, 10800)
print(timedelta)
# 2 days, 3:00:00
Similar modules
arrow: offers a sensible and human-friendly approach to creating, manipulating, formatting and converting dates, times and timestamps.
duration: python time duration conversion module
iso8601: Simple module to parse ISO 8601 dates
See also:
How can I parse and compare ISO 8601 durations in Python?
#hc_dev solution will work. However, I used a slightly different one that needed fewer additional modules. Just posting here for reference:
from datetime import datetime, timedelta
from dateutil import parser
def process_cmd_time(time_str, bound) -> datetime:
"""
Convert passed string to the datetime object.
Will throw ParseError or ValueError if the string is invalid
Keyword arguments:
time_str - string representation of the time to set
bound - flag to force time bound to 24h from now
"""
time_str = time_str.strip()
go_back = time_str[0] == '-'
# Attempt to get the date. Will throw ParseError if invalid
input_date = parser.parse(time_str)
# If the time needs to go back, find the delta from the beginning of today,
# then subtract from now
if go_back:
delta_today = input_date - parser.parse("0h0m0s")
input_date = datetime.now() - delta_today
if bound:
delta_time = datetime.now() - input_date
if delta_time.days > 0:
input_date = datetime.now() - timedelta(hours=24, minutes=0, seconds=0)
return input_date
As part of a function, I get the input of date and time plus time zone in the format "[YYYY]-[MM]-[DD]T[HH]:[MM]:[SS]+[XXXX]" (with XXXX being the difference to UTC in HHMM) and need the date and time as a Unix time stamp.
I'm currently using time.mktime([CONVERTED TIME]) but end up with TypeError: function takes exactly 9 arguments (6 given). It seems like a lot of effort to program something for the arguments of 'weekday' etc. for time.mktime, so I'm sure there's a better way which I just didn't find yet.
How else can this be done?
This is a ISO 8601 compliant timestamp. There are various libraries which can help with these. But is your case, for a fixed format, you can use Python's dt.datetime.strptime and datetime.timedelta to calculate the seconds since epoch like:
Code:
def epoch_seconds_from_iso_8601_with_tz_offset(iso_8601):
""" Convert ISO 8601 with a timezone offset to unix timestamp """
iso_8601_dt = dt.datetime.strptime(iso_8601[:-5], '%Y-%m-%dT%H:%M:%S')
utc_at_epoch = dt.datetime(1970, 1, 1)
epoch_without_tz_offset = (iso_8601_dt - utc_at_epoch).total_seconds()
tz_offset = 60 * (60 * int(iso_8601[-4:-2]) + int(iso_8601[-2:]))
if iso_8601[-5] == '-':
tz_offset = -tz_offset
return epoch_without_tz_offset - tz_offset
Test Code:
import datetime as dt
t1 = epoch_seconds_from_iso_8601_with_tz_offset('2018-01-07T19:43:15+0000')
t2 = epoch_seconds_from_iso_8601_with_tz_offset('2018-01-07T11:43:15-0800')
epoch = 1515354195
assert epoch == t1 == t2
I have this date string in python "2016-12-12T00:00:00+01:00"
How do I convert the said date string with timestamp to timestamp in milliseconds so I can compute use the value so I can compute it?
Purpose:
to_timestamp_milliseconds("2017-12-12T00:00:00+01:00") + (10500 * 1000)
Easy
dt = dateutil.parser.parse("2017-12-12T00:00:00+01:00")
timestamp = int(time.mktime(dt.timetuple()))
now you got seconds, I guess you can convert it to milliseconds your self
How can I compute the time differential between two time zones in Python? That is, I don't want to compare TZ-aware datetime objects and get a timedelta; I want to compare two TimeZone objects and get an offset_hours. Nothing in the datetime library handles this, and neither does pytz.
Here is a solution using the Python library Pytz which solves the issue of ambiguous times at the end of daylight saving time.
from pytz import timezone
import pandas as pd
def tz_diff(date, tz1, tz2):
'''
Returns the difference in hours between timezone1 and timezone2
for a given date.
'''
date = pd.to_datetime(date)
return (tz1.localize(date) -
tz2.localize(date).astimezone(tz1))\
.seconds/3600
The examples below calculate the difference in hours between UTC and Australia time for the first of January and first of June respectively. Notice how daylight savings are taken into consideration.
utc = timezone('UTC')
aus = timezone('Australia/Sydney')
tz_diff('2017-01-01', utc, aus)
# 11.0
tz_diff('2017-06-01', utc, aus)
# 10.0
Thanks
The first thing you have to know is that the offset between two time zones depends not only on the time zones in question, but on the date you're asking about. For example, the dates on which Daylight Savings Time began and ended changed in the US in 2007. While fundamental time zone logistics change only infrequently in any single location, the rate of change globally is impossible to ignore. Therefore, you have to incorporate the date in question into your function.
Having completed the necessary preface, the actual function isn't too hard to write if you take advantage of the pendulum library. It should look something like this:
import pendulum
def tz_diff(home, away, on=None):
"""
Return the difference in hours between the away time zone and home.
`home` and `away` may be any values which pendulum parses as timezones.
However, recommended use is to specify the full formal name.
See https://gist.github.com/pamelafox/986163
As not all time zones are separated by an integer number of hours, this
function returns a float.
As time zones are political entities, their definitions can change over time.
This is complicated by the fact that daylight savings time does not start
and end on the same days uniformly across the globe. This means that there are
certain days of the year when the returned value between `Europe/Berlin` and
`America/New_York` is _not_ `6.0`.
By default, this function always assumes that you want the current
definition. If you prefer to specify, set `on` to the date of your choice.
It should be a `Pendulum` object.
This function returns the number of hours which must be added to the home time
in order to get the away time. For example,
```python
>>> tz_diff('Europe/Berlin', 'America/New_York')
-6.0
>>> tz_diff('Europe/Berlin', 'Asia/Kabul')
2.5
```
"""
if on is None:
on = pendulum.today()
diff = (on.set(tz=home) - on.set(tz=away)).total_hours()
# what about the diff from Tokyo to Honolulu? Right now the result is -19.0
# it should be 5.0; Honolulu is naturally east of Tokyo, just not so around
# the date line
if abs(diff) > 12.0:
if diff < 0.0:
diff += 24.0
else:
diff -= 24.0
return diff
As stated in the documentation, you may not get a stable result for this between any two given locations as you sweep across the days of the year. However, implementing a variant which chooses the median result over the days of the current year is an exercise left for the reader.
Here's another solution:
from datetime import datetime
from pytz import timezone
from dateutil.relativedelta import relativedelta
utcnow = timezone('utc').localize(datetime.utcnow()) # generic time
here = utcnow.astimezone(timezone('US/Eastern')).replace(tzinfo=None)
there = utcnow.astimezone(timezone('Asia/Ho_Chi_Minh')).replace(tzinfo=None)
offset = relativedelta(here, there)
offset.hours
Here what we're doing is converting a time to two different time zones. Then, we remove the time zone information so that when you calculate the difference between the two using relativedelta, we trick it into thinking that these are two different moments in time instead of the same moment in different time zones.
The above result will return -11, however this amount can change throughout the year since US/Eastern observes DST and Asia/Ho_Chi_Minh does not.
I created two functions to deal with timezone.
import datetime
import pytz
def diff_hours_tz(from_tz_name, to_tz_name, negative=False):
"""
Returns difference hours between timezones
res = diff_hours_tz("UTC", "Europe/Paris") : 2
"""
from_tz = pytz.timezone(from_tz_name)
to_tz = pytz.timezone(to_tz_name)
utc_dt = datetime.datetime.now(datetime.timezone.utc)
dt_from = dt_to = datetime.datetime.utcnow()
dt_from = from_tz.localize(dt_from)
dt_to = to_tz.localize(dt_to)
from_d = dt_from - utc_dt
if from_d.days < 0:
return diff_hours_tz(to_tz_name, from_tz_name, True)
dt_delta = dt_from - dt_to
negative_int = -1 if negative else 1
return int(dt_delta.seconds/3600)*negative_int
def dt_tz_to_tz(dt, from_tz_name, to_tz_name):
"""
Apply difference hours between timezones to a datetime object
dt_new = dt_tz_to_tz(datetime.datetime.now(), "UTC", "Europe/Paris")
"""
hours = diff_hours_tz(from_tz_name, to_tz_name)
return dt+datetime.timedelta(hours=hours)
# Usage example
res = diff_hours_tz("Europe/Paris", "America/New_York")
# Result : -6
res = diff_hours_tz("UTC", "Europe/Paris")
# Result : 2
now = datetime.datetime.now()
# Result : 2019-06-18 15:10:31.720105
dt_new = dt_tz_to_tz(now, "UTC", "Europe/Paris")
# Result : 2019-06-18 17:10:31.720105
dt_new = dt_tz_to_tz(now, "Europe/Paris", "America/New_York")
# Result : 2019-06-18 09:10:31.720105
dt_new = dt_tz_to_tz(now, "America/New_York", "Europe/Paris")
# Result : 2019-06-18 21:10:31.720105
I hope it will help !
Here is a code snippet to get the difference between UTC and US/Eastern, but it should work for any two timezones.
# The following algorithm will work no matter what is the local timezone of the server,
# but for the purposes of this discussion, let's assume that the local timezone is UTC.
local_timestamp = datetime.now()
# Assume that utc_timestamp == 2019-01-01 12:00.
utc_timestamp = pytz.utc.localize(local_timestamp)
# If it was 12:00 in New York, it would be 20:00 in UTC. So us_eastern_timestamp is a UTC
# timestamp with the value of 2019-01-01 20:00.
us_eastern_timestamp = timezone("US/Eastern").localize(local_timestamp).astimezone(pytz.utc)
# delta is a Python timedelta object representing the interval between the two timestamps,
# which, in our example, is -8 hours.
delta = utc_timestamp - us_eastern_timestamp
# In the last line, we convert the timedelta into an integer representing the number of
# hours.
print round(delta.total_seconds() / 60.0 / 60.0)
(tz_from.localize(date) - tz_to.localize(date)).seconds/3600.0
Where tz_from and tz_to are the starting and ending timezones. You must specify a particular date.
from datetime import datetime
from zoneinfo import ZoneInfo
dt = datetime.now() # 2020-09-13
tz0, tz1 = "Europe/Berlin", "US/Eastern" # +2 vs. -4 hours rel. to UTC
utcoff0, utcoff1 = dt.astimezone(ZoneInfo(tz0)).utcoffset(), dt.astimezone(ZoneInfo(tz1)).utcoffset()
print(f"hours offset between {tz0} -> {tz1} timezones: {(utcoff1-utcoff0).total_seconds()/3600}")
>>> hours offset between Europe/Berlin -> US/Eastern timezones: -6.0
a way to do this with Python 3.9's standard library.