How to show ad banner depends on datetime? - python-3.x

I am trying to make a small algorithm to show an ad inside a container that contains a three banners but not to show all of them at once, I want to show just one every day.
Lets say each banner have to appear at a certain date time as showing bellow in the list:
ads = [
{
'banner': f'{ads_path}/1/ad_1917_175.gif',
'dtime': datetime.now() + timedelta(minutes=1)
},
{
'banner': f'{ads_path}/2/ad_1917x175.gif',
'dtime': datetime.now() + timedelta(minutes=2)
},
{
'banner': f'{ads_path}/3/ad_1917x175_2.gif',
'dtime': datetime.now() + timedelta(minutes=3)
}
]
all banners are saved inside database where I can filter each one by it offset, also I've created a datetime.now() variable to compare it with the dtime in my query, something like this:
dtime_now = datetime.now()
get_banner = Ads.query.filter(Ads.dtime < dtime_now).offset(1).limit(1)
From here I want to start, and the iteration will go to first banner if all dates inside database are smaller than the current time.
dtimes = [datetime.strptime(str(item.dtime), '%Y-%m-%d %H:%M:%S.%f') for item in get_ads]`
I've tried to combine the list of all dtimes to get them all in one datetime object, then to look if the result is smaller than the current time, that means go to first banner change it dtime and show it and so on.
But Python won't let you do that, because it just combines timedelta.
Any suggestions how to make that work? what is the best way to do that?

Not sure I'm following your logic, but you don't need a database to do this. How about:
ad_change_times = [datetime_1, datetime_2, datetime_3]
for i in range(len(ad_change_times)): # or range(1, len(ad_change_times)+1) if you insist on counting from 1
if datetime.now() > ad_change_times[i]:
banner = f'{ads_path}/{i}/ad_1917_175.gif',
break
Then, send that to your template.

Related

How to calculate average datetime timestamps in python3

I have a code which I have it's performance timestamped, and I want to measure the average of time it took to run it on multiple computers, but I just cant figure out how to use the datetime module in python.
Here is how my procedure looks:
1) I have the code which simply writes into a text file the log, where the timestamp looks like
t1=datetime.datetime.now()
...
t2=datetime.datetime.now()
stamp= t2-t1
And that stamp variable is just written in say log.txt so in the log file it looks like 0:07:23.160896 so it seems like it's %H:%M:%S.%f format.
2) Then I run a second python script which reads in the log.txt file and it reads the 0:07:23.160896 value as a string.
The problem is I don't know how to work with this value because if I import it as a datetime it will also append and imaginary year and month and day to it, which I don't want, I simply just want to work with hours and minutes and seconds and microseconds to add them up or do an average.
For example I can just open it in Libreoffice and add the 0:07:23.160896 to 0:00:48.065130 which will give 0:08:11.226026 and then just divide by 2 which will give 0:04:05.613013, and I just can't possibly do that in python or I dont know how to do it.
I have tried everything, but neither datetime.datetime, nor datetime.timedelta allows simply multiplication and division like that. If I just do a y=datetime.datetime.strptime('0:07:23.160896','%H:%M:%S.%f') it will just give out 1900-01-01 00:07:23.160896 and I can't just take a y*2 like that, it doesnt allow arithmetic operations, plus if if I convert it into a timedelta it will also multiply the year,which is ridiculous. I simply just want to add and subtract and multiply time.
Please help me find a way to do this, and not just for 2 variables but possibly even a way to calculate the average of an entire list of timestamps like average(['0:07:23.160896' , '0:00:48.065130', '0:00:14.517086',...]) way.
I simply just want a way to calculate the average of many timestamps and give out it's average in the same format, just as you can just select a column in Libreoffice and take the AVERAGE() function which will give out the average timestamp in that column.
As you have done, you first read the string into a datetime-object using strptime: t = datetime.datetime.strptime(single_time,'%H:%M:%S.%f')
After that, convert the time part of your datestring into a timedelta, so you can easily calculate with times: tdelta = datetime.timedelta(hours=t.hour, minutes=t.minute, seconds=t.second, microseconds=t.microsecond)
Now you can easily calculate with the timedelta object, and convert at the end of the calculations back into a string by str(tdsum)
import datetime
times = ['0:07:23.160896', '0:00:48.065130', '0:12:22.324251']
# convert times in iso-format into timedelta list
tsum = datetime.timedelta()
count = 0
for single_time in times:
t = datetime.datetime.strptime(single_time,'%H:%M:%S.%f')
tdelta = datetime.timedelta(hours=t.hour, minutes=t.minute, seconds=t.second, microseconds=t.microsecond)
tsum = tsum + tdelta
count = count + 1
taverage = tsum / count
average_time = str(taverage)
print(average_time)

Concatenating FOR loop output

I am very new to Python (first week of active use). I have some bash scripting experience but have decided to learn Python.
I have a variable of multiple strings which I am using to build a URL in FOR loop. The output of URL is JSON and I would like to concatenate complete output into one file.
I will put random URL for privacy reasons.
The code looks like this:
==================
numbers = ['24246', '83367', '37643', '24245', '24241', '77968', '63157', '76004', '71665']
for id in numbers:
restAPI = s.get(urljoin(baseurl, '/test/' + id + '&test2'))
result = restAPI.json
==================
the problem is that if I do print(result) I will get only output of last iteration, i.e. www.google.com/test/71665&test2
Creating a list by adding text = [] worked (content was concatenated) but I would like to keep the original format.
text = []
for id in numbers:
restAPI = s.get(urljoin(baseurl, '/test/' + id + '&test2'))
Does anyone have idea how to do this
When the for loop ends, the variable assigned inside the for loop only keeps the last value. I.e. Every time your code for loops through, the restAPI variable gets reset each time.
If you wanted to keep each URL, you could append to a list outside the scope of the for loop every time, i.e.
restAPI = s.get(urljoin(baseurl, ...
url_list.append(restApi.json)
Or if you just wanted to print...
for id in numbers:
restAPI = s.get(urljoin(baseurl, ...
print(restAPI.json)
If you added them to a list, you could perform seperate functions with the new list of URLs.
If you think there might be duplicates, feel free to use a set() instead (which automatically removes the dupes inside the iterable as new values are added). You can use set_name.add(restAPI.json)
To be better, you could implement a dict and assign the id as the key and the json object as the value. So you could:
dict_obj = dict()
for id in numbers:
restAPI = s.get(urljoin(baseurl, ...
dict_obj[id] = restAPI.json
That way you can query the dictionary later in the script.
Note that if you're querying many URLs, storing the JSON's in memory might be intensive depending on your hardware.

Holding int values in a list with a string, sorting by the int value

First of all here is the code I have so far for my small project.
# Problem: working out a percentage of minutes
# Inputs: percentage constant, empty list [activities], total activity time
PERCENTAGE = 100
activities = []
total_minutes = int(input('What was the total mobile phone usage (minutes) '))
# Loop: take users activity inputs
while sum(activities) < total_minutes:
activity_name = input('What was the activity? ')
activity_time = int(input('How many minutes on this activity? '))
# Add the activity to the list
activities = activities + [activity_name, activity_time]
print(activities)
'''Now, what I am aiming to do is have the activity name with the time spent on the activity in the list [activities]. I want to be able to retrieve either the activity name or time individually and to also "activities.sort()" by the integer value while obviously coinciding with the correct activity name.
Please make your answer as simple as possible (for someone in his early stage of university, second module)
Thanks in advance :)'''

How to increment counters based on a column value being fixed in a Window?

I have a dataset that, over time, indicates the region where certain users were located. From this dataset I want to calculate the number of nights that they spent at each location. By "spending the night" I mean: take the last location seen of a user until 23h59 of a certain day; if all observed locations from that user until 05:00 the next day, or the first one after that if there is none yet, match the last of the previous day, that's a night spent at that location.
| Timestamp| User| Location|
|1462838468|49B4361512443A4DA...|1|
|1462838512|49B4361512443A4DA...|1|
|1462838389|49B4361512443A4DA...|2|
|1462838497|49B4361512443A4DA...|3|
|1465975885|6E9E0581E2A032FD8...|1|
|1457723815|405C238E25FE0B9E7...|1|
|1457897289|405C238E25FE0B9E7...|2|
|1457899229|405C238E25FE0B9E7...|11|
|1457972626|405C238E25FE0B9E7...|9|
|1458062553|405C238E25FE0B9E7...|9|
|1458241825|405C238E25FE0B9E7...|9|
|1458244457|405C238E25FE0B9E7...|9|
|1458412513|405C238E25FE0B9E7...|6|
|1458412292|405C238E25FE0B9E7...|6|
|1465197963|6E9E0581E2A032FD8...|6|
|1465202192|6E9E0581E2A032FD8...|6|
|1465923817|6E9E0581E2A032FD8...|5|
|1465923766|6E9E0581E2A032FD8...|2|
|1465923748|6E9E0581E2A032FD8...|2|
|1465923922|6E9E0581E2A032FD8...|2|
I'm guessing I need to use Window functions here, and I've used PySpark for other things in the past, but I'm a bit at a loss as to where to start here.
I think in the end you do need to have a function that takes a series of events and outputs nights spent... something like (example just to get the idea):
def nights_spent(location_events):
# location_events is a list of events that have time and location
location_events = sort_by_time(location_events)
nights = []
prev_event = None
for event in location_events[1:]:
if prev_location is not None:
if next_day(prev_event.time, event.time) \
and same_location(prev_event.location, event.location):
# TODO: How do you handle when prev_event
# and event are more than 1 day apart?
nights.append(prev_location)
prev_location = location
return nights
Then, I think that a good first approach is to first group by user so that you get all events (with location and time) for a given user.
Then you can feed that list of events to the function above, and you'll have all the (user, nights_spent) rows in an RDD.
So, in general, the RDD would look something like:
nights_spent_per_user = all_events.map(lambda x => (x.user, [(x.time, x.location)])).reduce(lambda a, b: a + b).map(x => (x[0], nights_spent(x[1])))
Hope that helps to get you started.

Setting Loop with start and end date

Thats a code a friend of mine helped me with in order to get files from diferent measurement systems, timestamps and layout into on .csv file.
You enter the timeperiod or like in the case below 1 day and the code looks for this timestamps in different files and folders, adjusts timestamps (different Timezone etc.) and puts everything into one .csv file easy to plot. Now I need to rewrite that stuff for different layouts. I managed to get everything working but now I don't want to enter every single day manually into the code :-( , cause I'd need to enter it 3 times in a row --> in order to get the day for one day into one file, dateFrom and dateTo needs to be the same and in the writecsv...section you'd have to enter the date again.
here's the code:
from importer import cloudIndices, weatherall, writecsv,averagesolar
from datetime import datetime
from datetime import timedelta
dateFrom = datetime.strptime("2010-06-21", '%Y-%m-%d')
dateTo = datetime.strptime("2010-06-21", '%Y-%m-%d')
....
code
code
....
writecsv.writefile("data_20100621", header, ciData)
what can I change here so that I get an automatic loop for all data between e.g 2010-06-21 to 2011-06-21
p.s. if i'd entered 2010-06-21in dataFromand 2011-06-21 in dateTo i'd get a huge cvs. file with all the data in it ..... I thought that would be a great idea but it's not really good for plotting so I enden up manually entering day after day which isn't bad if you do it on a regular basis for 2 or 3 days but now a dates showed up and I need to rund the code over it :-(
Generally speaking you should be using datetime.datetime and datetime.timedelta, here is an example of how:
from datetime import datetime
from datetime import timedelta
# advance 5 days at a time
delta = timedelta(days=5)
start = datetime(year=1970, month=1, day=1)
end = datetime(year=1970, month=2, day=13)
print("Starting from: %s" % str(start))
while start < end:
print("advanced to: %s" % str(start))
start += delta
print("Finished at: %s" % str(start))
This little snippet creates a start and end time and a delta to advance using the tools python provides. You can modify it to fit your needs or apply it in your logic.

Resources