I am having problems with logic on how to convert military time from a text file to standard time and discard all the wrong values. I have only got to a point where the user is asked for the input file and the contents are displayed from the text file entered. Please help me
Python's datetime.time objects use "military" time. You can do things like this:
>>> t = datetime.time(hour=15, minute=12)
>>> u = datetime.time(hour=16, minute=44)
>>> t = datetime.datetime.combine(datetime.datetime.today(), t)
>>> t
datetime.datetime(2011, 5, 11, 15, 12)
>>> u = datetime.datetime.combine(datetime.datetime.today(), u)
>>> t - u
datetime.timedelta(-1, 80880)
With a little twiddling, conversions like the ones you describe should be pretty simple.
Without seeing any code, it's hard to tell what exactly you want. But I assume you could do something like this:
raw_time = '2244'
converted_time = datetime.time(hour=int(raw_time[0:2]), minute=int(raw_time[2:4]))
converted_time = datetime.datetime.combine(datetime.datetime.today(), converted_time)
Now you can work with converted_time, adding and subtracting timedelta objects. Fyi, you can create a timedelta like so:
td = datetime.timedelta(hours=4)
The full list of possible keyword arguments to the timedelta constructor is here.
from dateutil.parser import parse
time_today = parse("08:00")
from dateutil.relativedelta import relativedelta
required_time = time_today-relativedelta(minutes=35)
print required_time
datetime.datetime(2011, 5, 11, 7, 25)
It's not a true answer like the other two, but the philosophy I use when dealing with dates and times in python: convert to a datetime object as soon as possible after getting from the user, and only convert back into a string when you are presenting the value back to the user.
Most of the date/time math you will need can be done by datetime objects, and their cousins the timedelta objects. Unless you need ratios of timedeltas to other timedeltas, but that's another story.
Related
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")
In my Python 3.6 application, from my input data I can receive datatimes in two different formats:
"datefield":"12/29/2017" or "datefield":"2017-12-31"
I need to make sure the that I can handle either datetime format and convert them to (or leave it in) the iso 8601 format. I want to do something like this:
#python pseudocode
import datetime
if datefield = "m%/d%/Y%":
final_date = datetime.datetime.strptime(datefield, "%Y-%m-%d").strftime("%Y-%m-%d")
elif datefield = "%Y-%m-%d":
final_date = datefield
The problem is I don't know how to check the datefield for a specific datetime format in that first if-statement in my pseudocode. I want a true or false back. I read through the Python docs and some tutorials. I did see one or two obscure examples that used try-except blocks, but that doesn't seem like an efficient way to handle this. This question is unique from other stack overflow posts because I need to handle and validate two different cases, not just one case, where I can simply fail it if it does validate.
You can detect the first style of date by a simple string test, looking for the / separators. Depending on how "loose" you want the check to be, you could check a specific index or scan the whole string with a substring test using the in operator:
if "/" in datefield: # or "if datefield[2] = '/'", or maybe "if datefield[-5] = '/'"
final_date = datetime.datetime.strptime(datefield, "%m/%d/%Y").strftime("%Y-%m-%d")
Since you'll only ever deal with two date formats, just check for a / or a - character.
import datetime
# M/D/Y
if '/' in datefield:
final_date = datetime.datetime.strpdate(date, '%M/%D/%Y').isoformat()
# Y-M-D
elif '-' in datefield:
final_date = datetime.datetime.strpdate(date, '%Y-%M-%D').isoformat()
A possible approach is to use the dateutil library. It contains many of the commonest datetime formats and can automagically detect these formats for you.
>>> from dateutil.parser import parse
>>> d1 = "12/29/2017"
>>> d2 = "2017-12-31"
>>> parse(d1)
datetime.datetime(2017, 12, 29, 0, 0)
>>> parse(d2)
datetime.datetime(2017, 12, 31, 0, 0)
NOTE: dateutil is a 3rd party library so you may need to install it with something like:
pip install python-dateutil
It can be found on pypi:
https://pypi.python.org/pypi/python-dateutil/2.6.1
And works with Python2 and Python3.
Alternate Examples:
Here are a couple of alternate examples of how well dateutil handles random date formats:
>>> d3 = "December 28th, 2017"
>>> parse(d3)
datetime.datetime(2017, 12, 28, 0, 0)
>>> d4 = "27th Dec, 2017"
>>> parse(d4)
datetime.datetime(2017, 12, 27, 0, 0)
I went with the advice of #ChristianDean and used the try-except block in effort to be Pythonic. The first format %m/%d/%Y appears a bit more in my data, so I lead the try-except with that datetime formatting attempt.
Here is my final solution:
import datetime
try:
final_date = datetime.datetime.strptime(datefield, "%m/%d/%Y").strftime("%Y-%m-%d")
except ValueError:
final_date = datetime.datetime.strptime(datefield, "%Y-%m-%d").strftime("%Y-%m-%d")
I just started programming with Python, and have some simple questions (probably). What I would like to do is compare some timestamps to find the closest that isn't later then now.
Basically what Iam trying to do is getting the current track played on the radio, and they have a feed that show the next 20 or so with time for when the track starts. I want to get whats playing right now!
Here is an example array of strings:
examples = ['2012-12-10 02:06:45', '2012-12-10 02:02:43', '2012-12-10 01:58:53']
Now what I would like to do is compare the time closest to now (but not later) to see whats currently playing.
This is my script so far:
import datetime, itertools, time
currentTimeMachine = datetime.datetime.now()
now = currentTimeMachine.strftime("%Y-%m-%d %H:%M:%S")
examples = ['2012-12-10 02:06:45', '2012-12-10 02:02:43', '2012-12-10 01:58:53']
tmsg = examples.strftime('%d%b%Y')
print [x for x in itertools.takewhile( lambda t: now > datetime.datetime.strptime(t, "%Y-%m-%d %H:%M:%S"), examples )][-1]
The last bit there I picked up somwhere else, but I cant seem to get it to work.
Any help would be greatly appreciated!
The other answers have fixed your errors, so your algorithm now runs properly.
But the algorithm itself is wrong. You want to get the closest to the present without going over. But what you've written is:
[x for x in itertools.takewhile(pred, examples)][-1]
Think about what this means. First, takewhile will return examples until one of them fails the predicate. Then you're taking the last one that succeeded. So, if your examples looked like this:
[now-3, now-10, now-5, now+3, now-9, now-1, now+9]
First, takewhile will yield now-3, now-10, now-5 and then stop because pred(now+3) returns False. Then, you take the last one, now-5.
This would work if you sorted the examples in ascending order:
[now-10, now-9, now-5, now-3, now-1, now+3, now+9]
Now takewhile will yield everything up to now-1, so the last thing it yields is the one you want.
But the example in your initial question were in descending order, and in the comment to Anthony Kong's answer, you added some more that aren't in any order at all. So, you obviously can't rely on them being in sorted order. So, one possible fix is to sort them:
>>> import datetime, itertools, time
>>> currentTimeMachine = datetime.datetime.now()
>>> print [x for x in itertools.takewhile(lambda t: currentTimeMachine > datetime.datetime.strptime(t, "%Y-%m-%d %H:%M:%S"), sorted(examples))][-1]
2012-12-10 02:06:45
Or, to make things a bit more readable, break up that last line, and get rid of the extraneous list comprehension:
>>> exampleDates = [datetime.datetime.strptime(t, "%Y-%m-%d %H:%M:%S") for t in examples]
>>> def beforeNow(t):
... return currentTimeMachine > t
>>> print list(itertools.takewhile(beforeNow, sorted(exampleDates))[-1]
However, this is kind of a silly way to do things. What you really want is the maximum value in examples that isn't after the present. So just translate that English sentence into code:
>>> print max(x for x in exampleDates if x <= currentTimeMachine)
Let's put it all together:
>>> examples = ['2012-12-10 02:06:45', '2012-12-10 02:02:43', '2012-12-10 01:58:53']
>>> exampleDates = (datetime.datetime.strptime(t, "%Y-%m-%d %H:%M:%S") for t in examples)
>>> currentTimeMachine = datetime.datetime.now()
>>> print max(t for t in exampleDates if t <= currentTimeMachine)
2012-12-10 02:06:45
I used a generator expression rather than a list for exampleDates because you don't actually need the list for anything you just need to iterate over it once. If you want to keep it around for inspection or repeated use, change the parens to square brackets.
Also, I changed the < to <=, because you said "isn't later then now" rather than "is earlier than now" (in other words, now should count).
As a side note, because you happen to have ISO-esque timestamps, you actually can sort them as strings:
>>> now = datetime.datetime.now()
>>> currentTimeMachine = datetime.datetime.strftime(now, "%Y-%m-%d %H:%M:%S")
>>> print max(t for t in examples if t <= currentTimeMachine)
2012-12-10 02:06:45
There's no good reason to do things this way, and it will invariably lead you to bugs when you get timestamps in slightly different formats (e.g., '2012-12-10 02:06:45' compares before '2012-12-10Z01:06:45'), but it isn't actually a problem with your original code.
Since you did not post the error message, so based on the code your post, there are a few issues
1) tmsg = examples.strftime('%d%b%Y') won't work because you apply a call on strftime the list
2) As others have pointed out already, in the takewhile you're comparing string with datetime.
This will work:
>>> import datetime, itertools, time
>>> currentTimeMachine = datetime.datetime.now()
>>> print [x for x in itertools.takewhile( lambda t: currentTimeMachine > datetime.datetime.strptime(t, "%Y-%m-%d %H:%M:%S"), examples )][-1]
2012-12-10 01:58:53
Use datetime.datetime.strptime() to convert a string to a datetime object.
>>> import datetime
>>> examples = ['2012-12-10 02:06:45', '2012-12-10 02:02:43', '2012-12-10 01:58:53']
>>> parsed_datetimes = [datetime.datetime.strptime(e, "%Y-%m-%d %H:%M:%S") for e in examples]
>>> parsed_datetimes
[datetime.datetime(2012, 12, 10, 2, 6, 45), datetime.datetime(2012, 12, 10, 2, 2, 43), datetime.datetime(2012, 12, 10, 1, 58, 53)]
This will then get the minimum difference datetime, "closest to now", from the current datetime now:
>>> now = datetime.datetime.now()
>>> min_time_diff, min_datetime = min((now - i, i) for i in parsed_datetimes)
>>> min_time_diff, min_datetime
(datetime.timedelta(0, 36265, 626000), datetime.datetime(2012, 12, 10, 2, 6, 45))
I have a time format like this
t = "2012-03-20T08:31:00-05:00"
I can extract the time contents using RegEx like this.
p = re.compile("(\d{4})\-(\d\d)\-(\d\d)T(\d\d):(\d\d):(\d\d)[\-|+]\d\d:\d\d")
matches = p.findall(t)
But I was wondering if there is a way to convert this format directly to unix_timestamp without using RegEx ? Is there a calendar library or something similar ?
datetime.datetime.strptime is your friend :)
http://docs.python.org/library/datetime.html#datetime.datetime.strptime
Use time.strptime:
time.strptime(t, "%Y-%m-%dT%H:%M:%S-%Z")
Unfortunately, this doesn't appear to work with numeric time zone offsets. python-dateutil should be able to handle your format:
dateutil.parser.parse(t)
Alternatively, you could split your string before the numeric offset:
t, offset_sign, offset = t[:-6], t[-6], t[-5:]
t = time.strptime(t, "%Y-%m-%dT%H:%M:%S")
offset = time.strptime(offset, "%H:%M")
Use strptime from the time module
I'm writing a simple script which has a few lines like this:
if (datetime.datetime.hour == 12):
What is the easiest way to test these? Changing the system time to different times every time I want to test it is a bit annoying, is there an easier way to let Python think it's a different time?
Create a datetime object now and use it:
import datetime, pytz
testing = False # set to True/False
if testing:
now = datetime.datetime(2011, 1, 1, 12, 23, 34, tzinfo=pytz.utc)
# testing with any time
else:
now = datetime.datetime.now(pytz.utc)
# normal usage with current time
if (now.hour == 12):
...
EDIT: You can also start your script with an optional parameter (check optparse): if it is filled in a YYYYMMDDHHMMSS form, you can parse it:
if optDate:
now = datetime.datetime.strptime(optDate, '%Y%m%d%H%M%S').replace(tzinfo=pytz.utc)
else:
now = datetime.datetime.now(pytz.utc)
Apply your own timezone here if you want.