How to find difference between two timestamps in Python? - python-3.x

I need to find the difference between two timestamps in minutes.
I am using Python 3.6.
Here is my script:
import datetime
from dateutil import parser
indate = str(datetime.datetime.utcnow())
indate2 = parser.parse(indate)
indate3 = indate2.date()
intime = indate2.time()
outdate1 = "2019-10-16T06:38:55.000+0000"
outdate2 = parser.parse(outdate1)
outdate3 = outdate2.date()
outtime = outdate2.time()
### ---THEN PRINT DIFFERENCE BETWEEN THE TWO IN MINUTES --- ###

It will be advisable to ensure that they both have the same timezone:
(indate2.astimezone(datetime.timezone.utc) - outdate2).total_seconds()/60
Out[161]: 494.60840941666663

You need to remove the timezone awarenes from outdate2
print(indate2 - outdate2.replace(tzinfo=None))

Related

Python3 Datetime (delta) to Seconds (Including Days)

Hopefully just a simple question. I want to convert a datetime object to seconds and include the days. I've just noticed that my code skipped the day. Please note times are just an example and not 100% accurate.
Content of oldtime.txt (2 days ago):
2021-09-16 19:34:33.569827
Code:
oldtimefile = open('oldtime.txt', 'r+')
oldtme = oldtimefile.read()
datetimeobj = datetime.strptime(oldtme, "%Y-%m-%d %H:%M:%S.%f")
finaltime = datetime.now() - datetimeobj
print(finaltime.seconds)
If I just print finaltime then I get 1 day, 22:13:30.231916.
Now if we take today's date and time - just for argument sake - (2021-09-18 17:34:33.569827) as now then I actually get 80010 seconds instead of roughly 172800 seconds. It's ignoring the day part.
How can I include the day and convert the entire object to seconds?
Thanks.
Instead of .seconds you can use .total_seconds():
from datetime import datetime
oldtme = "2021-09-16 19:34:33.569827"
datetimeobj = datetime.strptime(oldtme, "%Y-%m-%d %H:%M:%S.%f")
finaltime = datetime.now() - datetimeobj
print(finaltime.total_seconds())
Prints:
164254.768354

tz.localize() returning incorrect offset

I have the following function (with exaggerated logger statements just to help with debugging right now) that takes an input timezone and datetime, and converts it to PST:
def convert_to_pst_equivalent_time(input_datetime, input_timezone):
timezone = pytz.timezone(input_timezone)
dt_date = input_datetime.split("T")[0]
dt_time = input_datetime.split("T")[1].split("-")[0] if "-" in input_datetime.split("T")[1] else \
input_datetime.split("T")[1].split("+")[0]
dt = datetime.strptime((dt_date + " " + dt_time), "%Y-%m-%d %H:%M:%S")
logger.info("DT is: {}".format(dt))
dt = timezone.localize(dt)
logger.info("DT is now: {}".format(dt))
dt = dt.astimezone(pytz.timezone("America/Los_Angeles"))
logger.info("DT is finally: {}".format(dt))
return dt.strftime("%Y-%m-%dT%H:%M:%S")
If we have some inputs like "2020-02-03T00:00:00" as "input_datetime" and "Pacific/Norwalk" as the input_timezone, my outputs are the following:
DT is: 2020-02-03 00:00:00
DT is now: 2020-02-03 00:00:00+12:00
DT is finally: 2020-02-02 04:00:00-08:00
However, based on this website (https://www.zeitverschiebung.net/en/difference/timezone/pacific--norfolk/city/5368361), Pacific/Norwalk should be +11:00, not +12:00, and therefore, my final output after converting to Los Angeles time is also off by 1 hour. Strangely, this is working for other timezones, but this one in particular is offering problems. I've tried doing things like replacing tzinfo= and localize() (as seen above) but neither appear to be returning the right offset. Any ideas?

Setting variable to compare file modification between multiple dates

I'm trying to compare two text files that are date specific, but I'm stumped. I created a test folder that has three text files in it with modified dates between one and 35 days old.
I.E: red.txt is 35 days old, blue.txt is one day old, and green.txt is 15 days old.
For my two compared files, the first file must be between a range of 13-15 days and the second one day old or less. So for this example, 'green.txt' will become 'file1' and 'blue.txt' will become 'file2' and then be compared with difflib, but I'm having trouble with the syntax, or maybe even the logic. I am using datetime with timedelta to try to get this working, but my results will always store the oldest modified file that is past 15 days for 'file1'. Here's my code:
import os, glob, sys, difflib, datetime as d
p_path = 'C:/test/Text_file_compare_test/'
f_list = glob.glob(os.path.join(p_path, '*.txt'))
file1 = ''
file2 = ''
min_days_ago = d.datetime.now() - d.timedelta(days=1)
max_days_ago = d.datetime.now() - d.timedelta(days=13 <= 15)
for file in f_list:
filetime = d.datetime.fromtimestamp(os.path.getmtime(file))
if filetime < max_days_ago:
file1 = file
if filetime > min_days_ago:
file2 = file
with open(file1) as f1, open(file2) as f2:
d = difflib.Differ()
result = list(d.compare(f1.readlines(), f2.readlines()))
sys.stdout.writelines(result)
I'm certain there is something wrong with code:
max_days_ago = d.datetime.now() - d.timedelta(days=13 <= 15)
Maybe I'm just not seeing something in the datetime module that's obvious. Can someone shed some light for me? Also, this is on Windows 10 Python 3.7.2. Thanks in advance!
As per my comment, your d.timedelta(days=13 <= 15) isn't quite right as you are assigning days to a boolean value of true, which will be equivalent to d.timedelta(days=1). You need to store 3 separate time points and do your 13-15 day comparison against two different dates. The code below demonstrates what you are looking for I believe:
import datetime as d
files = {
'red': d.datetime.now() - d.timedelta(days=35),
'blue': d.datetime.now() - d.timedelta(days=0, hours=12),
'green': d.datetime.now() - d.timedelta(days=14),
}
days_ago_1 = d.datetime.now() - d.timedelta(days=1)
days_ago_13 = d.datetime.now() - d.timedelta(days=13)
days_ago_15 = d.datetime.now() - d.timedelta(days=15)
file1 = None
file2 = None
for file, filetime in files.items():
if days_ago_13 >= filetime >= days_ago_15:
file1 = file
elif filetime > days_ago_1:
file2 = file
# need to break out of the loop when we are finished
if file1 and file2:
break
print(file1, file2)
prints green blue

inbuilt parser in Python for handling dates like : 05/May/2010:12:01:15 +0000

In a logfile, I have my date and time recorded in the format :
[05/May/2010:12:01:15 +0000]
I am trying to extract only the time from the above in Python3.x. I was mainly looking for a inbuilt parser in Python3.x. I ran into different formats except for this. I came up with a solution in JAVA using the below code and I am looking for something similar in Python3.x. Is there one ? Or do I have to write my own parser for extracting the date,time out of this ? Here is the JAVA code of what I wanted :
//field[3] contains "[25/May/2015:23:11:15 +0000]"
String timeStamp = fields[3].substring(1,fields[3].length()).split(" ")[0];
SimpleDateFormat df = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss",Locale.US);
Date d = null;
try {
d = df.parse(timeStamp);
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("Time :"+ d.getTime());// Prints 23:11:15
You can use time.strptime() to parse it into a time.struct_time object:
import time
your_field = "[25/May/2015:23:11:15 +0000]"
parsed = time.strptime(your_field, "[%d/%b/%Y:%H:%M:%S %z]")
# NOTE: %z depends on implementation, you might need to remove the timezone info
# before parsing your date/time with `time.strptime()`.
# print time:
print(time.strftime("%H:%M:%S", parsed))
# prints: 23:11:15
But if you just want to get the time you don't need to parse it just to build it again, instead you can just substring it out:
your_field = "[25/May/2015:23:11:15 +0000]"
your_time = your_field.split(":", 1)[1].split(" ", 1)[0]
# print time:
print(your_time)
# prints: 23:11:15
Here is a solution using datetime.strptime:
from datetime import datetime
field3 = '[25/May/2015:23:11:15 +0000]'
result = datetime.strptime(field3, '[%d/%b/%Y:%H:%M:%S %z]')
print(result.strftime("%H:%M:%S"))
Output
23:11:15

how to convert a string to a dateutil weekday tuple without using eval

I'm using dateutil to generate a schedule based on an input file.
my config file looks like this:
[alarm1]
time = 8:00
days = MO
[alarm2]
time = 9:00
days = TU, WE
[alarm3]
time = 22:00
days = MO, WE, FR
etc..
I'm using dateutil to generate a schedule based off this.
here's some sample code, where I omitted the control flows and import code for the sake of brevity.
from dateutil.rrule import *
from dateutil.parser import *
import datetime
import configparser
alarms = rruleset()
time = parse(alarm_parser.get(alarm_section, 'time')).time()
date = datetime.date.today()
alarm_time= datetime.datetime.combine(date, time)
days = '(' + alarm_parser.get(alarm_section, 'days') + ',)'
alarm_days = eval(days)
alarms.rrule(rrule(WEEKLY, dtstart = alarm_datetime, byweekday = alarm_days, count = 1))
this code now works thanks to eval However, eval apparently risky.
I've tried rrulestr(), but the command doesn't seem to accept byweekday = as part of the argument.
how do I convert the string in the config file to a tuple that rrule can work with without using eval? I've tried ast.literal_eval, but that gives me the following error
ValueError: malformed node or string: <_ast.Name object at 0xb68e2430>
I needed a slightly more complex version of Paul's simple code (one that could handle parenthesized offsets like "FR(+2)"). Here is what I came up with:
import re
from dateutil.rrule import MO, TU, WE, TH, FR, SA, SU
_daymap = {"MO": MO, "TU": TU, "WE": WE, "TH": TH, "FR": FR, "SA": SA, "SU": SU}
_dayre = re.compile(r"(MO|TU|WE|TH|FR|SA|SU)(?=\(([-+]?[0-9]+)\))?")
def parsedays(daystr):
for day in daystr.split(","):
m = _dayre.match(day.strip())
if m:
weekday, offset = m.groups()
result = _daymap[weekday]
if offset:
result = result(int(offset))
yield result
def dumpdays(days):
return ",".join(str(d) for d in days)
Tested using Python 3.7.3
The simple way to do this is some variation on this:
from dateutil.rrule import MO, TU, WE, TH, FR, SA, SU
daymap = {'MO': MO, 'TU': TU, 'WE': WE, 'TH': TH, 'FR': FR, 'SA': SA, 'SU': SU}
daystr = 'TU, TH'
days = [daymap[day.strip()] for day in daystr.split(',')]
However, you can also accomplish this with rrulestr using the BYDAY (not BYWEEKDAY) parameter:
from dateutil.rrule import rrulestr
base_rrstr = ('DTSTART:{alarm_datetime:%Y%m%dT%H%M%S}\n' +
'FREQ={freq_str};COUNT={count_str};BYDAY={day_str}')
alarm_datetime = datetime.datetime.today()
freq_str = "WEEKLY"
count_str = "1"
day_str = "TU,TH"
crr = rrulestr(base_rrstr.format(alarm_datetime=alarm_datetime,
freq_str=freq_str,
count_str=count_str,
day_str=day_str))

Resources