Python ,Duration Calcution between Timestamps - python

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

Related

Python command parameter indicating time delta

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

How to compute the time difference between two time zones in python?

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.

Python - How to convert datetime data using toordinal considering the time

Let's assume that I have the following data:
25/01/2000 05:50
When I convert it using datetime.toordinal, it returns this value:
730144
That's nice, but this value just considers the date itself. I also want it to consider the hour and minutes (05:50). How can I do it using datetime?
EDIT:
I want to convert a whole Pandas Series.
An ordinal date is by definition only considering the year and day of year, i.e. its resolution is 1 day.
You can get the microseconds / milliseconds (depending on your platform) from epoch using
datetime.datetime.strptime('25/01/2000 05:50', '%d/%m/%Y %H:%M').timestamp()
for a pandas series you can do
s = pd.Series(['25/01/2000 05:50', '25/01/2000 05:50', '25/01/2000 05:50'])
s = pd.to_datetime(s) # make sure you're dealing with datetime instances
s.apply(lambda v: v.timestamp())
If you use python 3.x. You can get date with time in seconds from 1/1/1970 00:00
from datetime import datetime
dt = datetime.today() # Get timezone naive now
seconds = dt.timestamp()

Python strptime - Handling single digit dates

I've been working on trying to convert a given time to a different format, taking into account an external device's timezone, skipping the OS's timezone conversions.
Initially, I have a time in UTC seconds, and the timezone from the device. For example, where I am right now the time is seconds=1343931446, and timezone = -0700. What I'm trying to do is convert this to the format YYYYMMDD_HHMMSS, which has worked properly for a while. For the above values, it should come out to be 20120802_111726.
This following block of code worked since I wrote it, conveniently on July 11th. The issue comes down to the fact that when the day is only 1 digit long (aka starting yesterday), the parsing goes wrong, and I get 20120821_011726. I'm presuming the issue is when I convert the time value into date time, as when I print time_t, I'll get time.struct_time(tm_year=2012, tm_mon=8, tm_mday=2, tm_hour=18, tm_min=17, tm_sec=26, tm_wday=3, tm_yday=215, tm_isdst=0), which is treated as single character strings when parsed into a datetime.
The question is, can I force datetime to accept a 2-character input for the day of the month/hour so it will parse properly, or is there a better way of transforming these formats? Keep in mind that this current method was written due to not being able to use any methods that account for the current system time, as this is done where the time zone is not guaranteed to be same on the system as the device that the seconds were obtained from.
def convert_time(seconds, tz):
""" Times obtained were in seconds since epoch.
Convert to format YYYYMMDD_HHMMSS.
"""
time_t = time.gmtime(seconds) # convert to time tuple
# convert to datetime format - because time zone comparisons can't be made
# in a format directly convertible from UTC
time_dt = datetime.datetime.strptime(str(time_t.tm_year) +
str(time_t.tm_mon) +
str(time_t.tm_mday) +
str(time_t.tm_hour) +
str(time_t.tm_min) +
str(time_t.tm_sec),
'%Y%m%d%H%M%S')
# Convert time zone to timedelta
offset = datetime.timedelta(hours=int(tz.lstrip('-')[:2]),
minutes=int(tz.lstrip('-')[2:]))
sign = -1 if tz.startswith('-') else 1
time_dt = time_dt + sign * offset
time_dt = time_dt.strftime('%Y%m%d_%H%M%S')
return time_dt
Your timestamp is expressed in seconds, your timezone in hours and minutes. Simply subtract or add the timezone converted to seconds, then use the time.strftime function to format that to the string you want:
def convertTime(seconds, tz):
tzhours, tzminutes = map(int, (tz.lstrip('-')[:2], tz[-2:]))
offset = tzhours * 3600 + tzminutes * 60
if tz.startswith('-'):
offset *= -1
return time.strftime('%Y%m%d_%H%M%S', time.gmtime(seconds + offset))

How to convert integer into date object python?

I am creating a module in python, in which I am receiving the date in integer format like 20120213, which signifies the 13th of Feb, 2012. Now, I want to convert this integer formatted date into a python date object.
Also, if there is any means by which I can subtract/add the number of days in such integer formatted date to receive the date value in same format? like subtracting 30 days from 20120213 and receive answer as 20120114?
This question is already answered, but for the benefit of others looking at this question I'd like to add the following suggestion: Instead of doing the slicing yourself as suggested in the accepted answer, you might also use strptime() which is (IMHO) easier to read and perhaps the preferred way to do this conversion.
import datetime
s = "20120213"
s_datetime = datetime.datetime.strptime(s, '%Y%m%d')
I would suggest the following simple approach for conversion:
from datetime import datetime, timedelta
s = "20120213"
# you could also import date instead of datetime and use that.
date = datetime(year=int(s[0:4]), month=int(s[4:6]), day=int(s[6:8]))
For adding/subtracting an arbitary amount of days (seconds work too btw.), you could do the following:
date += timedelta(days=10)
date -= timedelta(days=5)
And convert back using:
s = date.strftime("%Y%m%d")
To convert the integer to a string safely, use:
s = "{0:-08d}".format(i)
This ensures that your string is eight charecters long and left-padded with zeroes, even if the year is smaller than 1000 (negative years could become funny though).
Further reference: datetime objects, timedelta objects
Here is what I believe answers the question (Python 3, with type hints):
from datetime import date
def int2date(argdate: int) -> date:
"""
If you have date as an integer, use this method to obtain a datetime.date object.
Parameters
----------
argdate : int
Date as a regular integer value (example: 20160618)
Returns
-------
dateandtime.date
A date object which corresponds to the given value `argdate`.
"""
year = int(argdate / 10000)
month = int((argdate % 10000) / 100)
day = int(argdate % 100)
return date(year, month, day)
print(int2date(20160618))
The code above produces the expected 2016-06-18.
import datetime
timestamp = datetime.datetime.fromtimestamp(1500000000)
print(timestamp.strftime('%Y-%m-%d %H:%M:%S'))
This will give the output:
2017-07-14 08:10:00

Categories

Resources