I have two DateTime strings. How would I compare them and tell which comes first?
A = '2019-02-12 15:01:45:145'
B = '2019-02-12 15:02:02:22'
This format has milliseconds in it, so it cannot be parsed by time.strptime. I chose to split according to the last colon, parse the left part, and manually convert the right part, add them together.
A = '2019-02-12 15:01:45:145'
B = '2019-02-12 15:02:02:22'
import time
def parse_date(s):
date,millis = s.rsplit(":",1)
return time.mktime(time.strptime(date,"%Y-%m-%d %H:%M:%S")) + int(millis)/1000.0
print(parse_date(A))
print(parse_date(B))
prints:
1549958505.145
1549958522.022
now compare the results instead of printing them to get what you want
If your convention on milliseconds is different (ex: here 22 could also mean 220), then it's slightly different. Pad with zeroes on the right, then parse:
def parse_date(s):
date,millis = s.rsplit(":",1)
millis = millis+"0"*(3-len(millis)) # pad with zeroes
return time.mktime(time.strptime(date,"%Y-%m-%d %H:%M:%S")) + int(millis)/1000.0
in that case the result it:
1549958505.145
1549958522.22
If both the date/time strings are in ISO 8601 format (YYYY-MM-DD hh:mm:ss) you can compare them with a simple string compare, like this:
a = '2019-02-12 15:01:45.145'
b = '2019-02-12 15:02:02.022'
if a < b:
print('Time a comes before b.')
else:
print('Time a does not come before b.')
Your strings, however, have an extra ':' after which come... milliseconds? I'm not sure. But if you convert them to a standard hh:mm:ss.xxx... form, then your date strings will be naturally comparable.
If there is no way to change the fact that you're receiving those strings in hh:mm:ss:xx format (I'm assuming that xx is milliseconds, but only you can say for sure), then you can "munge" the string slightly by parsing out the final ":xx" and re-attaching it as ".xxx", like this:
def mungeTimeString(timeString):
"""Converts a time string in "YYYY-MM-DD hh:mm:ss:xx" format
to a time string in "YYYY-MM-DD hh:mm:ss.xxx" format."""
head, _, tail = timeString.rpartition(':')
return '{}.{:03d}'.format(head, int(tail))
Then call it with:
a = '2019-02-12 15:01:45:145'
b = '2019-02-12 15:02:02:22'
a = mungeTimeString(a)
b = mungeTimeString(b)
if a < b:
print('Time a comes before b.')
else:
print('Time a does not come before b.')
Related
def convert(time):
pos = ["s","m","h","d"]
time_dict = {"s": 1,"m": 60,"h": 3600,"d": 24*3600 }
unit = time[-1]
if unit not in pos:
return -1
try:
timeVal = int(time[:-1])
except:
return -2
return timeVal*time_dict[unit]
Currently, this is my code and I'm using it to translate Strings like 5d or 30m to seconds. And that's work, but if I try to combine them (like 5d 30m, it gives me the output -2. I don't really see what's wrong here.
Your problem is that you're only checking the last character, you need to parse the string to find each individual group and then work off of that
import re
def convert(time):
time_dict = {"s": 1,"m": 60,"h": 3600,"d": 24*3600 }
regex_groups = re.findall("(\d+)([smhd])", time)
return sum(int(x) * time_dict[y] for x,y in regex_groups)
I don't really see what's wrong here.
Lets say you provided 5d 30m as input, [:-1] does jettison last character which result in 5d 30. You then try to convert it to int which fails, as d is not allowed in integer representation.
You need first to tokenize elements then convert every piece to value in seconds then sum them together, simplified example with h and m only:
def to_seconds(token):
q = {"h":3600,"m":60}
return int(token[:-1])*q[token[-1]]
def convert(time):
return sum(to_seconds(i) for i in time.split())
print(convert("5h 30m"))
output
19800
Disclaimer: this solution assumes that elements are whitespaces sheared
I'm doing an application which parse a XML from http request and one of the attributes is a date.
The problem is that the format is a string without separation, for example: '20190327200000000W' and I need to transform it into a datetime format to send it to a database.
All the information I have found is with some kind of separation char (2019-03-23 ...). Can you help me?
Thanks!!!
Maybe this? (in jupypter notebook)
from datetime import datetime
datetime_object = datetime.strptime('20190327200000000W', '%Y%m%d%H%M%S%fW')
datetime_object
Well I have solved this, at first I did that Xenobiologist said, but I had a format problem, so I decided to delete the last character (the X of %X)...and I realized that I hadn't a string, I had a list, so I transformed to string and did the operations. My code (I'll put only the inside for loop part, without the parsing part):
for parse in tree.iter(aaa):
a = parse.get(m)
respon = a.split(' ')
if m == 'Fh':
x = str(respon[0])
x2 = len(x)
x3 = x[:x2-1]
print (x3)
y = time.strptime(x3, "%Y%m%d%H%M%S%f")
I have the following code:
comments = sorted(comments, key=lambda k: k['time_created'])
How to sort correctly if some elements have the different format, like 2017-12-14T17:42:30.345244+0000 and 2017-12-14 00:23:23.468560 and my code fail when trying to compare?
I need to save seconds accuracy.
Is it the good solution?
comments = sorted(comments, key=lambda k: self.unix_time_millis(k['time_created']), reverse=True)
#staticmethod
def unix_time_millis(dt):
epoch = datetime.datetime.utcfromtimestamp(0)
return (dt - epoch).total_seconds() * 1000.0
Python datetime objects are comparable and therefore sortable. I assume that you currently don't use datetime objects but Strings. The following example code is taken from
How to format date string via multiple formats in python
import dateutil.parser
dateutil.parser.parse(date_string)
You would then convert a list of strings to datetime objects via
list_of_dt_objs = [dateutil.parser.parse(str) for str in list_of_strings]
Please note that dateutil is an extension lib. So you have to install it, for instance via pip.
Something like this:
import re
import operator
def convert_to_secs(date_string):
multipliers = [31557600,2592000,86400,3600,60]
date_in_secs = 0
index = 0
for v in re.split(':|-|T|\.|\+|\ ',date_string):
if index < len(multipliers):
date_in_secs = date_in_secs + int(v) * multipliers[index]
index += 1
else:
break
return date_in_secs
def sort_dates(my_dates_in_string):
my_dates_dict = {}
for string_date in my_dates_in_string:
my_dates_dict[string_date] = convert_to_secs(string_date)
return sorted(my_dates_dict.items(), key=operator.itemgetter(1))
print sort_dates(["2017-12-14T17:42:30.345244+0000", "2017-12-14 00:23:23.468560"])
I am trying to return the element of a list based on a comparison between two other lists.
List 1 is a list of file names created from using glob.glob(path).
List 2 is identical to the first, but has the filenames parsed into datetimes using datetime.datetime.strptime. It is by definition the same length as the first list.
List 3 list is like the second, in that it is a list of datetimes parsed from a list of filenames. The lists of filenames are related, but not necessarily the same length.
What I am trying to do is return the filename (List 1) that corresponds to the last datetime in List 2 prior to a specific element of List 3. It's confusing, I know. Sorry about that.
I know that using next is a quick way to return values from a list based on comparisons, but I haven't found a way to use it to return a value from a list outside the comparison.
Here's what I have:
# get list of mat files and extract corresponding times
matFiles = []
matFileTimes = []
matFilePattern = re.compile('\\.*(\w*\s*\w*\s*)(\d+.\d+.\d+\s+\d+.\d+.\d+.\d+)(\s*\w*\s*\d*)?\.mat$')
for name in glob.glob(filePath[0] + '\*.mat'):
event = re.search(matFilePattern, name)
matFiles.append(event.group(0))
matFileTimes.append(datetime.datetime.strptime(event.group(2),'%Y-%m-%d %H-%M-%S-%f'))
self.matFiles = sorted(matFiles)
self.matFileTimes = sorted(matFileTimes)
if 'audio' in listdir(filePath[0]):
audioFiles = []
audioFileTimes = []
audioFilePattern = re.compile('\\.*(\w*\s*\w*\s*)(\d+.\d+.\d+\s+\d+.\d+.\d+.\d+)?\.wav$')
for name in glob.glob(path.join(filePath[0], 'audio') + '\*.wav'):
audioEvent = re.search(audioFilePattern, name)
audioFiles.append(audioEvent.group(0))
audioFileTimes.append(datetime.datetime.strptime(audioEvent.group(2),'%Y-%m-%d %H-%M-%S-%f'))
self.audioFiles = sorted(audioFiles)
self.audioFileTimes = sorted(audioFileTimes)
for each in audioFileTimes:
self.eventMenu.addItem(datetime.datetime.strftime(each, '%b %d %Y, %I:%M:%S %p'))
else:
for each in matFileTimes:
self.eventMenu.addItem(datetime.datetime.strftime(each, '%b %d %Y, %I:%M:%S %p'))
Then later (in a different class function):
if 'audio' in listdir(self.filePath):
fileToLoad = next(dt for dt in reversed(self.matFileTimes) if dt <= self.audioFileTimes[self.eventMenu.currentIndex()])
As it's implemented, next returns the datetime from "matFileTimes" that occurs immediately prior to the datetime indicated by the "eventMenu". What's the quickest Pythonic way to return the element of "matFiles" that corresponds to the "matFileTime" datetime?
Suggestions on better ways to do anything shown are also appreciated - I'm a bit new at this.
The quickest way to get a result is using the index of the file time element and get the element with the same index of the file name list:
if 'audio' in listdir(self.filePath):
timeToLoad = next(dt for dt in reversed(self.matFileTimes) if dt <= self.audioFileTimes[self.eventMenu.currentIndex()])
fileToLoad = self.matFiles[self.matFileTimes.index(timeToLoad)]
I have a Python script that generates .csv files from other data sources.
Currently, an error happens when the user manually adds a space to a date by accident. Instead of inputting the date as "1/13/17", a space may be added at the front (" 1/13/17") so that there's a space in front of the month.
I've included the relevant part of my Python script below:
def processDateStamp(sourceStamp):
matchObj = re.match(r'^(\d+)/(\d+)/(\d+)\s', sourceStamp)
(month, day, year) = (matchObj.group(1), matchObj.group(2), matchObj.group(3))
return "%s/%s/%s" % (month, day, year)
How do I trim the space issue in front of month and possibly on other components of the date (the day and year) as well for the future?
Thanks in advance.
Since you're dealing with dates, it might be more appropriate to use datetime.strptime than regex here. There are two advantages of this approach:
It makes it slightly clearer to anyone reading that you're trying to parse dates.
Your code will be more prone to throw exceptions when trying to parse data that doesn't represent dates, or represent dates in an incorrect format - this is good because it helps you catch and address issues that might otherwise go unnoticed.
Here's the code:
from datetime import datetime
def processDateStamp(sourceStamp):
date = datetime.strptime(sourceStamp.replace(' ', ''), '%M/%d/%y')
return '{}/{}/{}'.format(date.month, date.day, date.year)
if __name__ == '__main__':
print(processDateStamp('1/13/17')) # 1/13/17
print(processDateStamp(' 1/13/17')) # 1/13/17
print(processDateStamp(' 1 /13 /17')) # 1/13/17
You also can use parser from python-dateutil library. The main benefit you will get - it can recognize the datetime format for you (sometimes it may be useful):
from dateutil import parser
from datetime import datetime
def processDateTimeStamp(sourceStamp):
dt = parser.parse(sourceStamp)
return dt.strftime("%m/%d/%y")
processDateTimeStamp(" 1 /13 / 17") # returns 01/13/17
processDateTimeStamp(" jan / 13 / 17")
processDateTimeStamp(" 1 - 13 - 17")
processDateTimeStamp(" 1 .13 .17")
Once again, a perfect opportunity to use split, strip, and join:
def remove_spaces(date_string):
date_list = date_string.split('/')
result = '/'.join(x.strip() for x in date_list)
return result
Examples
In [7]: remove_spaces('1/13/17')
Out[7]: '1/13/17'
In [8]: remove_spaces(' 1/13/17')
Out[8]: '1/13/17'
In [9]: remove_spaces(' 1/ 13/17')
Out[9]: '1/13/17'