Time intervals as strings python - python

Im pretty new at programming and right now I'm working with Zoo in python, a programme where the user can put in a time interval by choice during the opening hours of the zoo. The Zoo is open from 07-23, and for example the bear is available from 08-18 to look at.
for example.
What time do you wish to visit the Zoo?
input by user: 10-13
At this time you can see the animals:
...
...
And the programme will write out exactly what animals are available for show at that time interval. Given our example, the bear will be available and be printed out.
Im wondering how I can easy make the programme translate the input by the user to a string or maybe with range, so I dont have to create a hundred different varibles like 06-06, 06-07, 06-08, 06-09 etc.
Any ideas?
Thanks!

I'd solve this by changing the ask a little bit to the following:
What time will you arrive at the Zoo? 9 am on 11/11/2015
How long would you like to stay? 3 hrs
This will let you use a nice date picker widget on the front end which you can then create a datetime object for the start. Next, create a timedelta object for the duration. You can apply the delta the the start object to get the end time so you don't have to worry about parsing.
The other reason I recommend this is anecdotally I've seen evidence that users perceive start and duration and more clear/easier to use rather than picking two times. Per the above, you plan on spending 4 hours at the Zoo, not being there specifically from X to Y, so this UI better matches the mental model.

You can store each interval as a pair of integers corresponding to the start/end of the time interval:
from collections import namedtuple
Interval = namedtuple('Interval', 'start end')
If you have a string such as '10-13'; you could convert it to Interval:
user_hours = Interval(*map(int, '10-13'.split('-')))
# -> Interval(start=10, end=13)
To find out "what animals are available for show at that time interval", you need to know whether two given time intervals intersect:
def intersect(a, b):
return a.start < b.end and b.start < a.end
Example:
>>> intersect(Interval(8,18), Interval(10,13))
True
There are no overnight intervals and therefore you could treat the time intervals as linear (intervals on a line).
Now, you only need to populate the table with visiting hours for zoo animals:
visiting_hours = {
"bear": Interval(8, 18), # 08-18
"lion": Interval(14, 16), # 14-16
}
and you can print which animals are available for the given user hours:
for animal, available_hours in visiting_hours:
if intersect(user_hours, available_hours):
print(animal)
As an alternative you could use datetime.time() instead of int to represent hours -- it enforces valid values (0..23) for hours automatically:
from datetime import datetime
while True:
user_input = input("Input time interval e.g., 10-13: ")
try:
user_hours = Interval(*[datetime.strptime(h, "%H").time()
for h in user_input.split('-')])
except ValueError as e:
print("Invalid input: %s. Try again." % (e,))
else:
break
Modify the "visiting hours" table accordingly:
from datetime import time
visiting_hours = {
"bear": Interval(time(8), time(18)),
"lion": Interval(time(14), time(16)),
}
You could automate the input e.g., by reading the visiting hours from a file.
The rest of the code stays the same.
You could save the visiting hours into a separate file e.g., SQLite database and edit the table independently (using another script):
#!/usr/bin/env python
import sqlite3
db = sqlite3.connect(':memory:') # create in memory for debugging
db.execute('''CREATE TABLE intervals
(animal text, start integer, end integer)''')
# populate
visiting_hours = [('bear', '08-18'), ('lion', '14-16')]
db.executemany('INSERT INTO intervals VALUES (?, ?, ?)',
[[animal] + list(map(int, hours.split('-')))
for animal, hours in visiting_hours])
To get the animals from the database:
# "what animals are available for show at that time interval"
for animal, in db.execute('''SELECT animal FROM intervals
WHERE ? < end and start < ?''',
tuple(map(int, '10-13'.split('-')))):
print(animal)

Related

How to get a set of all time between range of start and end time?

I want to get all the time between start time and end time in python, so I was using for loop with range function.
There are 2 variables, a and b which have time in %H:%M:%S format.
These 2 variables are start and end time and I want to print all the time between the start and end time.
import datetime
from datetime import datetime
import time
a = '20:15:16'
b = '20:32:55'
a = datetime.strptime(a,'%H:%M:%S').time()
b = datetime.strptime(b,'%H:%M:%S').time()
for i in range(a,b):
print(i)
For this I am getting an error - datetime.time' object cannot be interpreted as an integer.
I want to print all the time between a and b.
There are infinite moments between two times. I think you might be asking, "How can I print a timestamp for every second or every minute between A and B?"
I don't think you want to be using the range function. The error you are seeing is because range expects integers as input, not whole datetime objects.
Here is something that may do what you want:
from datetime import datetime, timedelta
# Define our times
str_A = '20:15:16'
str_B = '20:32:55'
# Create our datetime objects
A = datetime.strptime(str_A,'%H:%M:%S')
B = datetime.strptime(str_B,'%H:%M:%S')
# Create a loop where you print a time, starting with time A
# and then increase the time stamp by some value, in this case,
# 1 minute, until you reach time B
tmp = a
while tmp <= b:
print(tmp.time())
tmp = tmp + timedelta(minutes=1)
Please notice the line,
print(tmp.time())
where we only extract the time part when we need it, leaving the object as a datetime object for easy manipulation.
I used this question for reference:
What is the standard way to add N seconds to datetime.time in Python?
So this question is really adorable. There is something about reading, 'I need to print "all the time" between these two times' that gives me joy.

add hours to time string to match time zone in python

I have a string that looks like this
time = "2020-04-15 21:27"
That's based on normal time zone +0
how can i add hours to the string so it become like this
for example let's add 5 hours to the time
the time string will become like this
time = "2020-04-15 02:27"
then the day should be updated
so the final result will look like this
time = "2020-04-15 02:27"
how can i do that ?
Edit:
i also need to change the day because 24 hours have passed
It is unclear if you mean creating your own clock or just updating a string every hour.
Option one:
import time
While True:
t = time.ctime(%h)
print(t)
#the above produces a live clock only showing hours.
#you could add %s for seconds separated by commas and thd like.
Option 2:
import time
T = #whatever you want it to be
time.sleep(300)
T = the prev num bit you want to change + 5
Hope this helps!
Happy coding

How to convert time written "h.mm" to decimal form with Python?

I prompt the user to input what time they start and finish their job. Then I need to calculate what they will earn (given a 97 currency/hour salary). The answer should also not have any decimals (so it should be rounded off). I can't seem to get it to work though.
As shown below, I tried taking the difference between the two inputs from the user and then splitting them to hours and minutes. After that just doing the calculations.
difference = round(float(finishing_time)-float(start_time), 2)
hours, minutes = str(difference).split(".")
salary_hours = int(hours)*97
salary_minutes = int(minutes)//60*97
salary = salary_hours + salary_minutes
So if start_time = 8.30 and finishing_time = 11.15 the salary should be 267, but I get 291 currency.
A couple of things to be careful of, is the rounding off that occurs at every level, which also occurs when you do math by hand and pencil! There is a reason why when you perform calculations one typically does the rounding off when the entire calculation has been performed otherwise one would come up with a vastly different answer as you pointed out.
I'd tackle this perhaps by doing something like this
from datetime import datetime
# quick way to generate a datetime object with start time would be like
start_time = datetime.now()
# replace the hours and minutes you want in your case its
start_time = start_time.replace(hour=8, minute=30)
end_time = start_time.replace(hour=11, minute=15)
# calling replace returns a new distinct datetime object
def calculate_salary(start_time, finish_time, pay_rate):
# will be in seconds
delta_seconds = finish_time - start_time
# convert to hours
hours_worked = (delta_seconds.seconds) / 3600
# calculate pay
pay = hours_worked * pay_rate
return pay
In this case calling the function gives a value of
In [1]: calculate_salary(start_time, end_time, 97)
Out[1]: 266.75
While i dont advocate doing calculations on time without a time module. I assume you know what your doing and that your calculations are simple I.E they wont rolle over midnight and the finish time will always be greater than the start time and finish on the same day. With that in mind the following code should produce your result without using a datetime module. However like #william bright answer, a datetime module would be my prefernce for code like this.
def get_hours(time_string):
time_split = time_string.split(".")
whole_hours = int(time_split[0])
fraction_hours = int(time_split[1]) / 60
return whole_hours + fraction_hours
start_time=input("start time: ")
finish_time=input("finish_time: ")
total_hours = get_hours(finish_time)-get_hours(start_time)
salary = total_hours*97
print(round(salary))
OUTPUT
start time: 8.30
finish_time: 11.15
267
So, my bad for perhaps being unclear in my statement, but since this is a work in progress for the next couple weeks/months, what I came up with was the following:
starting_time = input("At what time did you start working? ")
finishing_time = input("At what time did you finish working? ")
hours1, minutes1 = starting_time.split(".")
hours2, minutes2 = finishing_time.split(".")
minutes1 = float(minutes1)/60
starting_time_new = float(hours1)+minutes1
minutes2 = float(minutes2)/60
finishing_time_new = float(hours2)+minutes2
salary = round((finishing_time_new-starting_time_new)*97)
print("Started working at:",b)
print("Stopped working at:",s)
print("Your salary is",salary,"currency.")
The solution from where I started was to just focus on changing the minutes to the correct decimals instead of focusing on the hours too.
I am well aware that it is far from perfect, in fact, it is probably really bad. However, I am new to programming in Python and taking a course to be better.

Sorting my list by hours and printing a table,

I feel like I'm so close to the answer but after trying various methods suggested on similar problem on this site, I'm not closer to the answer.
I've tagged in the actual assignment what I borrowed from here (so I'm not accidentally stealing code) but removed it here to make it easier to read. What I'm looking to do is keep my three functions (that is taking the input, removing the colon, and then printing a sorted table from the list i.e.:
"Enter time for your next appointment (as hh:mm): 17:30
Enter a short description: COSC1306
Appointment at 17:30 COSC 1306"
This is what I have:
alpha = []
while len(alpha) >= 0:
gamma = input("Enter time for your next appointment (as hh:mm): ")
(h, m) = gamma.split(':')
result = str(h) + str(m)
delta = input("Enter a short description: ")
alpha.append([result, delta])
sorted(alpha)
for table in alpha:
print("Appointment at %s %s" %(table[0],", ".join(map(str,table[1:]))))
I want the table to be sorted by what "time" the appointment is and not just in the order I typed it. Is there anyone who might be able to help me with that?
I think replacing sorted(alpha) with the following should work:
alpha = sorted(alpha, key=lambda x: (x[0]))
Try this:
print(alpha)
sorted(alpha)
print(alpha)
Notice that alpha is unchanged. sorted returns a NEW list, which is immediately discarded. If you want to sort in-place, do
alpha.sort()

Python timedelta receiving unexpected results

In a web application I'm writing for an existing database I need to calculate the difference between now and a timestamp stored in the database (in a text field, it's stupid, I know). Here's my sqlalchemy Ban class and the relevant method.
class Ban(base):
__tablename__= 'bans'
id= Column('banID', Integer, primary_key=True)
unban_timestamp= Column('UNBAN', Text)
banned_steamid= Column('ID', Text, ForeignKey('rp_users.steamid'))
banned_name= Column('NAME', Text)
banner_steamid= Column('BANNER_STEAMID', Text, ForeignKey('rp_users.steamid'))
banner_name= Column('BANNER', Text)
reason= Column('REASON', Text)
def unbanned_in(self, mode):
if self.unban_timestamp == '0':
return 'Never'
else:
now= datetime.datetime.utcnow()
time= datetime.datetime.fromtimestamp(int(self.unban_timestamp))
if now > time:
return 'Expired'
else:
remaining= time - now
if mode=='readable':
return remaining
elif mode=='int':
return str(remaining.seconds).zfill(10)
I need both the integer and the pretty string representations because I'll be presenting this in a html table and javascript needs a simple way to sort it. The problem I'm facing is that the integers and strings are not matching up, as you can see in this screenshot here:
if anyone can make sense of why the output is so screwed up that would be appreciated! if there's any more information that you need to answer my question I'll gladly add it.
edit
for the record at the top of the screenshot the unbanned_in timestamp is 1320247970 if I run that through my function this is the result I get
>>> ban = session.query(db.Ban).filter_by(id=3783).one()
>>> print ban.unbanned_in('int'), ban.unbanned_in('readable')
0000049044 2 days, 13:37:24.179045
If you want to get the number of seconds between time and now, use
remaining.days * 24 * 3600 + remaining.seconds
instead of just remaining.seconds
The output is screwed up because your calculation to convert a number of seconds to days, hours, minutes and seconds is wrong. Since you didn't post that bit of code that's all I can say, but note that there are 86400 seconds in a day and all of the counts of seconds you output are smaller than this.
The values you output for hours, minutes and seconds look fine, just your calculation for days is wrong.

Categories