1
0
mirror of https://github.com/krateng/maloja.git synced 2023-08-10 21:12:55 +03:00

Complete rework of time descriptors, Part II

This commit is contained in:
Krateng 2019-04-10 15:45:50 +02:00
parent 652bc7eb94
commit e3a6201b4b
11 changed files with 320 additions and 182 deletions

View File

@ -15,6 +15,7 @@ import datetime
import sys import sys
import unicodedata import unicodedata
import json import json
import pickle
from collections import namedtuple from collections import namedtuple
from threading import Lock from threading import Lock
# url handling # url handling
@ -384,9 +385,9 @@ def get_pulse(**keys):
rngs = ranges(**{k:keys[k] for k in keys if k in ["since","to","within","step","stepn","trail"]}) rngs = ranges(**{k:keys[k] for k in keys if k in ["since","to","within","step","stepn","trail"]})
results = [] results = []
for (a,b) in rngs: for rng in rngs:
res = len(db_query(since=a,to=b,**{k:keys[k] for k in keys if k in ["artists","artist","track","title","associated"]})) res = len(db_query(timerange=rng,**{k:keys[k] for k in keys if k in ["artists","artist","track","title","associated"]}))
results.append({"from":a,"to":b,"scrobbles":res}) results.append({"range":rng,"scrobbles":res})
return results return results
@ -408,22 +409,22 @@ def get_performance(**keys):
rngs = ranges(**{k:keys[k] for k in keys if k in ["since","to","within","step","stepn","trail"]}) rngs = ranges(**{k:keys[k] for k in keys if k in ["since","to","within","step","stepn","trail"]})
results = [] results = []
for (a,b) in rngs: for rng in rngs:
if "track" in keys: if "track" in keys:
charts = get_charts_tracks(since=a,to=b) charts = get_charts_tracks(timerange=rng)
rank = None rank = None
for c in charts: for c in charts:
if c["track"] == keys["track"]: if c["track"] == keys["track"]:
rank = c["rank"] rank = c["rank"]
break break
elif "artist" in keys: elif "artist" in keys:
charts = get_charts_artists(since=a,to=b) charts = get_charts_artists(timerange=rng)
rank = None rank = None
for c in charts: for c in charts:
if c["artist"] == keys["artist"]: if c["artist"] == keys["artist"]:
rank = c["rank"] rank = c["rank"]
break break
results.append({"from":a,"to":b,"rank":rank}) results.append({"range":rng,"rank":rank})
return results return results
@ -900,7 +901,7 @@ cacheday = (0,0,0)
def db_query(**kwargs): def db_query(**kwargs):
check_cache_age() check_cache_age()
global cache_query global cache_query
key = json.dumps(kwargs) key = pickle.dumps(kwargs)
if key in cache_query: return copy.copy(cache_query[key]) if key in cache_query: return copy.copy(cache_query[key])
result = db_query_full(**kwargs) result = db_query_full(**kwargs)
@ -911,7 +912,7 @@ cache_aggregate = {}
def db_aggregate(**kwargs): def db_aggregate(**kwargs):
check_cache_age() check_cache_age()
global cache_aggregate global cache_aggregate
key = json.dumps(kwargs) key = pickle.dumps(kwargs)
if key in cache_aggregate: return copy.copy(cache_aggregate[key]) if key in cache_aggregate: return copy.copy(cache_aggregate[key])
result = db_aggregate_full(**kwargs) result = db_aggregate_full(**kwargs)
@ -942,9 +943,9 @@ def check_cache_age():
# Queries the database # Queries the database
def db_query_full(artist=None,artists=None,title=None,track=None,since=None,to=None,within=None,associated=False,max_=None): def db_query_full(artist=None,artists=None,title=None,track=None,since=None,to=None,within=None,timerange=None,associated=False,max_=None):
(since, to) = time_stamps(since,to,within) (since, to) = time_stamps(since=since,to=to,within=within,range=timerange)
# this is not meant as a search function. we *can* query the db with a string, but it only works if it matches exactly # this is not meant as a search function. we *can* query the db with a string, but it only works if it matches exactly
# if a title is specified, we assume that a specific track (with the exact artist combination) is requested # if a title is specified, we assume that a specific track (with the exact artist combination) is requested
@ -993,8 +994,10 @@ def db_query_full(artist=None,artists=None,title=None,track=None,since=None,to=N
# Queries that... well... aggregate # Queries that... well... aggregate
def db_aggregate_full(by=None,since=None,to=None,within=None,artist=None): def db_aggregate_full(by=None,since=None,to=None,within=None,timerange=None,artist=None):
(since, to) = time_stamps(since,to,within)
(since, to) = time_stamps(since=since,to=to,within=within,range=timerange)
if isinstance(artist, str): if isinstance(artist, str):
artist = ARTISTS.index(artist) artist = ARTISTS.index(artist)

View File

@ -42,7 +42,7 @@ def module_scrobblelist(max_=None,pictures=False,shortTimeDesc=False,earlystop=F
for s in scrobbles: for s in scrobbles:
html += "<tr>" html += "<tr>"
html += "<td class='time'>" + time_desc(s["time"],short=shortTimeDesc) + "</td>" html += "<td class='time'>" + timestamp_desc(s["time"],short=shortTimeDesc) + "</td>"
if pictures: if pictures:
img = scrobbleimages[i] img = scrobbleimages[i]
else: img = None else: img = None
@ -81,12 +81,11 @@ def module_pulse(max_=None,**kwargs):
#build list #build list
html = "<table class='list'>" html = "<table class='list'>"
for t in ranges: for t in ranges:
fromstr = "/".join([str(e) for e in t["from"]]) range = t["range"]
tostr = "/".join([str(e) for e in t["to"]])
html += "<tr>" html += "<tr>"
html += "<td>" + range_desc(t["from"],t["to"],short=True) + "</td>" html += "<td>" + range.desc() + "</td>"
html += "<td class='amount'>" + scrobblesLink({"since":fromstr,"to":tostr},amount=t["scrobbles"],**kwargs_filter) + "</td>" html += "<td class='amount'>" + scrobblesLink({"since":range.fromstr(),"to":range.tostr()},amount=t["scrobbles"],**kwargs_filter) + "</td>"
html += "<td class='bar'>" + scrobblesLink({"since":fromstr,"to":tostr},percent=t["scrobbles"]*100/maxbar,**kwargs_filter) + "</td>" html += "<td class='bar'>" + scrobblesLink({"since":range.fromstr(),"to":range.tostr()},percent=t["scrobbles"]*100/maxbar,**kwargs_filter) + "</td>"
html += "</tr>" html += "</tr>"
html += "</table>" html += "</table>"
@ -117,13 +116,12 @@ def module_performance(max_=None,**kwargs):
#build list #build list
html = "<table class='list'>" html = "<table class='list'>"
for t in ranges: for t in ranges:
fromstr = "/".join([str(e) for e in t["from"]]) range = t["range"]
tostr = "/".join([str(e) for e in t["to"]])
html += "<tr>" html += "<tr>"
html += "<td>" + range_desc(t["from"],t["to"],short=True) + "</td>" html += "<td>" + range_desc(t["from"],t["to"],short=True) + "</td>"
html += "<td class='rank'>" + ("#" + str(t["rank"]) if t["rank"] is not None else "No scrobbles") + "</td>" html += "<td class='rank'>" + ("#" + str(t["rank"]) if t["rank"] is not None else "No scrobbles") + "</td>"
prct = (minrank+1-t["rank"])*100/minrank if t["rank"] is not None else 0 prct = (minrank+1-t["rank"])*100/minrank if t["rank"] is not None else 0
html += "<td class='chart'>" + rankLink({"since":fromstr,"to":tostr},percent=prct,**kwargs_filter,medal=t["rank"]) + "</td>" html += "<td class='chart'>" + rankLink({"since":range.fromstr(),"to":range.tostr()},percent=prct,**kwargs_filter,medal=t["rank"]) + "</td>"
html += "</tr>" html += "</tr>"
html += "</table>" html += "</table>"
@ -288,13 +286,13 @@ def module_toptracks(pictures=True,**kwargs):
#fromstr = "/".join([str(p) for p in e["from"]]) #fromstr = "/".join([str(p) for p in e["from"]])
#tostr = "/".join([str(p) for p in e["to"]]) #tostr = "/".join([str(p) for p in e["to"]])
limits = pickKeys(e,"since","to") range = e["range"]
i += 1 i += 1
html += "<tr>" html += "<tr>"
html += "<td>" + range_desc(e["since"],e["to"],short=True) + "</td>" html += "<td>" + range.desc() + "</td>"
if e["track"] is None: if e["track"] is None:
if pictures: if pictures:
html += "<td><div></div></td>" html += "<td><div></div></td>"
@ -307,8 +305,8 @@ def module_toptracks(pictures=True,**kwargs):
img = getTrackImage(e["track"]["artists"],e["track"]["title"],fast=True) img = getTrackImage(e["track"]["artists"],e["track"]["title"],fast=True)
else: img = None else: img = None
html += entity_column(e["track"],image=img) html += entity_column(e["track"],image=img)
html += "<td class='amount'>" + scrobblesTrackLink(e["track"],internal_to_uri(limits),amount=e["scrobbles"]) + "</td>" html += "<td class='amount'>" + scrobblesTrackLink(e["track"],{"since":range.fromstr(),"to":range.tostr()},amount=e["scrobbles"]) + "</td>"
html += "<td class='bar'>" + scrobblesTrackLink(e["track"],internal_to_uri(limits),percent=e["scrobbles"]*100/maxbar) + "</td>" html += "<td class='bar'>" + scrobblesTrackLink(e["track"],{"since":range.fromstr(),"to":range.tostr()},percent=e["scrobbles"]*100/maxbar) + "</td>"
html += "</tr>" html += "</tr>"
prev = e prev = e
html += "</table>" html += "</table>"
@ -344,13 +342,13 @@ def module_topartists(pictures=True,**kwargs):
#fromstr = "/".join([str(p) for p in e["from"]]) #fromstr = "/".join([str(p) for p in e["from"]])
#tostr = "/".join([str(p) for p in e["to"]]) #tostr = "/".join([str(p) for p in e["to"]])
limits = pickKeys(e,"since","to") range = e["range"]
i += 1 i += 1
html += "<tr>" html += "<tr>"
html += "<td>" + range_desc(e["since"],e["to"],short=True) + "</td>" html += "<td>" + range.desc() + "</td>"
if e["artist"] is None: if e["artist"] is None:
if pictures: if pictures:
@ -363,8 +361,8 @@ def module_topartists(pictures=True,**kwargs):
img = getArtistImage(e["artist"],fast=True) img = getArtistImage(e["artist"],fast=True)
else: img = None else: img = None
html += entity_column(e["artist"],image=img) html += entity_column(e["artist"],image=img)
html += "<td class='amount'>" + scrobblesArtistLink(e["artist"],internal_to_uri(limits),amount=e["scrobbles"],associated=True) + "</td>" html += "<td class='amount'>" + scrobblesArtistLink(e["artist"],{"since":range.fromstr(),"to":range.tostr()},amount=e["scrobbles"],associated=True) + "</td>"
html += "<td class='bar'>" + scrobblesArtistLink(e["artist"],internal_to_uri(limits),percent=e["scrobbles"]*100/maxbar,associated=True) + "</td>" html += "<td class='bar'>" + scrobblesArtistLink(e["artist"],{"since":range.fromstr(),"to":range.tostr()},percent=e["scrobbles"]*100/maxbar,associated=True) + "</td>"
html += "</tr>" html += "</tr>"
prev = e prev = e
html += "</table>" html += "</table>"

View File

@ -55,7 +55,30 @@ date = expandeddate
# only for ranges, timestamps are separate # only for ranges, timestamps are separate
class MTime: class MRangeDescriptor:
def __eq__(self,other):
return self.first_stamp() == other.first_stamp() and self.last_stamp() == other.last_stamp()#
def __hash__(self):
return hash((self.first_stamp(),self.last_stamp()))
def info(self):
return {
"fromstring":self.fromstr(),
"tostr":self.tostr(),
"uri":self.uri(),
"fromstamp":self.first_stamp(),
"tostamp":self.last_stamp(),
"description":self.desc()
}
def uri(self):
return "&".join(k + "=" + self.urikeys[k] for k in self.urikeys)
# a range that is exactly a gregorian calendar unit (year, month or day)
class MTime(MRangeDescriptor):
def __init__(self,*ls): def __init__(self,*ls):
# in case we want to call with non-unpacked arguments # in case we want to call with non-unpacked arguments
if isinstance(ls[0],tuple) or isinstance(ls[0],list): if isinstance(ls[0],tuple) or isinstance(ls[0],list):
@ -72,9 +95,13 @@ class MTime:
def __str__(self): def __str__(self):
return "/".join(str(part) for part in self.tup) return "/".join(str(part) for part in self.tup)
def fromstr(self):
return str(self)
def tostr(self):
return str(self)
def uri(self): def urikeys(self):
return "in=" + str(self) return {"in":str(self)}
def desc(self,prefix=False): def desc(self,prefix=False):
if self.precision == 3: if self.precision == 3:
@ -140,9 +167,30 @@ class MTime:
day = self.last_day().dateobject + datetime.timedelta(days=1) day = self.last_day().dateobject + datetime.timedelta(days=1)
return int(datetime.datetime.combine(day,datetime.time(tzinfo=datetime.timezone.utc)).timestamp() - 1) return int(datetime.datetime.combine(day,datetime.time(tzinfo=datetime.timezone.utc)).timestamp() - 1)
# next range of equal length (not exactly same amount of days, but same precision level)
def next(self,step=1):
if self.precision == 1:
return MTime(self.year + step)
elif self.precision == 2:
dt = [self.year,self.month]
dt[1] += step
while dt[1] > 12:
dt[1] -= 12
dt[0] += 1
while dt[1] < 1:
dt[1] += 12
dt[0] -= 1
return MTime(*dt)
elif self.precision == 3:
dt = self.dateobject
d = datetime.timedelta(days=step)
newdate = dt + d
return MTime(newdate.year,newdate.month,newdate.day)
class MTimeWeek:
# a range that is exactly one christian week (starting on sunday)
class MTimeWeek(MRangeDescriptor):
def __init__(self,year=None,week=None): def __init__(self,year=None,week=None):
self.year = year self.year = year
self.week = week self.week = week
@ -158,9 +206,13 @@ class MTimeWeek:
def __str__(self): def __str__(self):
return str(self.year) + "/W" + str(self.week) return str(self.year) + "/W" + str(self.week)
def fromstr(self):
return str(self)
def tostr(self):
return str(self)
def uri(self): def urikeys(self):
return "in=" + str(self) return {"in":str(self)}
def desc(self,prefix=False): def desc(self,prefix=False):
if prefix: if prefix:
@ -195,8 +247,15 @@ class MTimeWeek:
day = self.lastday + datetime.timedelta(days=1) day = self.lastday + datetime.timedelta(days=1)
return int(datetime.datetime.combine(day,datetime.time(tzinfo=datetime.timezone.utc)).timestamp() - 1) return int(datetime.datetime.combine(day,datetime.time(tzinfo=datetime.timezone.utc)).timestamp() - 1)
def next(self,step=1):
try:
return MTimeWeek(self.year,self.week + step)
except:
pass
# TODO
class MRange: # a range that is defined by separate start and end
class MRange(MRangeDescriptor):
def __init__(self,since=None,to=None): def __init__(self,since=None,to=None):
since,to = time_pad(since,to) since,to = time_pad(since,to)
@ -205,12 +264,17 @@ class MRange:
def __str__(self): def __str__(self):
return str(self.since) + " - " + str(self.to) return str(self.since) + " - " + str(self.to)
def fromstr(self):
return str(self.since)
def tostr(self):
return str(self.to)
def uri(self):
keys = [] def urikeys(self):
if self.since is not None: keys.append("since=" + uri(self.since)) keys = {}
if self.to is not None: keys.append("&to=" + uri(self.to)) if self.since is not None: keys["since"] = str(self.since)
return "&".join(keys) if self.to is not None: keys["to"] = str(self.to)
return keys
def desc(self,prefix=False): def desc(self,prefix=False):
if self.since is not None and self.to is not None: if self.since is not None and self.to is not None:
@ -239,9 +303,25 @@ class MRange:
return self.to.last_day() return self.to.last_day()
def first_stamp(self): def first_stamp(self):
return self.since.first_stamp() if self.since is None: return FIRST_SCROBBLE
else: return self.since.first_stamp()
def last_stamp(self): def last_stamp(self):
return self.to.last_stamp() if self.to is None: return int(datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).timestamp())
else: return self.to.last_stamp()
def next(self,step=1):
# hop from the start element by one until we reach the end element
diff = 1
nxt = self.since
while (nxt != self.to):
diff += 1
nxt = nxt.next(step=1)
newstart = self.since.next(step=diff*step)
newend = self.to.next(step=diff*step)
return MRange(newstart,newend)
## test ## test
@ -258,7 +338,8 @@ def time_str(t):
# converts strings and stuff to objects # converts strings and stuff to objects
def time_fix(t): def time_fix(t):
if t is None: return None
if isinstance(t,MRangeDescriptor): return t
if isinstance(t, str): if isinstance(t, str):
tod = datetime.datetime.utcnow() tod = datetime.datetime.utcnow()
@ -294,13 +375,28 @@ def time_fix(t):
if isinstance(t[1],str) and t[1].startswith("W"): if isinstance(t[1],str) and t[1].startswith("W"):
try: try:
year = int(t[0])
weeknum = int(t[1][1:]) weeknum = int(t[1][1:])
return MTimeWeek(year=t[0],week=t[1]) return MTimeWeek(year=year,week=weeknum)
except: except:
pass raise
def get_range_object(since=None,to=None,within=None):
since,to,within = time_fix(since),time_fix(to),time_fix(within)
# check if we can simplify
if since is not None and to is not None and since == to: within = since
# TODO
if within is not None:
return within
else:
return MRange(since,to)
# makes times the same precision level # makes times the same precision level
@ -325,6 +421,8 @@ def time_pad(f,t,full=False):
return f,t return f,t
def range_desc(f,t,short=False):
return MRange(time_fix(f),time_fix(t)).desc()
@ -363,33 +461,34 @@ def timestamp_desc(t,short=False):
def time_stamps(since=None,to=None,within=None): def time_stamps(since=None,to=None,within=None,range=None):
if range is None: range = get_range_object(since=since,to=to,within=within)
if within is not None: return range.first_stamp(),range.last_stamp()
since = within #print(range.desc())
to = within # if (since==None): stamp1 = FIRST_SCROBBLE
# else: stamp1 = range.first_stamp()
# if (to==None): stamp2 = int(datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).timestamp())
# else: stamp2 = range.last_stamp()
# return stamp1,stamp2
if (since==None): stamp1 = FIRST_SCROBBLE # if (since==None): stamp1 = FIRST_SCROBBLE
else: # else:
since = time_fix(since) # stamp1 = since1
date = [1970,1,1] # since = time_fix(since)
date[:len(since)] = since # date = [1970,1,1]
stamp1 = int(datetime.datetime(date[0],date[1],date[2],tzinfo=datetime.timezone.utc).timestamp()) # date[:len(since)] = since
# stamp1 = int(datetime.datetime(date[0],date[1],date[2],tzinfo=datetime.timezone.utc).timestamp())
if (to==None): stamp2 = int(datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).timestamp()) #
else: # if (to==None): stamp2 = int(datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).timestamp())
to = time_fix(to) # else:
to = _get_next(to) # to = time_fix(to)
date = [1970,1,1] # to = _get_next(to)
date[:len(to)] = to # date = [1970,1,1]
stamp2 = int(datetime.datetime(date[0],date[1],date[2],tzinfo=datetime.timezone.utc).timestamp()) # date[:len(to)] = to
# stamp2 = int(datetime.datetime(date[0],date[1],date[2],tzinfo=datetime.timezone.utc).timestamp())
#
return (stamp1,stamp2-1) #
# return (stamp1,stamp2-1)
@ -406,93 +505,115 @@ def delimit_desc(step="month",stepn=1,trail=1):
def ranges(since=None,to=None,within=None,step="month",stepn=1,trail=1,max_=None): def day_from_timestamp(stamp):
dt = datetime.datetime.utcfromtimestamp(stamp)
return MTime(dt.year,dt.month,dt.day)
def month_from_timestamp(stamp):
dt = datetime.datetime.utcfromtimestamp(stamp)
return MTime(dt.year,dt.month)
def year_from_timestamp(stamp):
dt = datetime.datetime.utcfromtimestamp(stamp)
return MTime(dt.year)
def week_from_timestamp(stamp):
dt = datetime.datetime.utcfromtimestamp(stamp)
d = date(dt.year,dt.month,dt.day)
y,w,_ = d.chrcalendar()
return MTimeWeek(y,w)
(firstincluded,lastincluded) = time_stamps(since=since,to=to,within=within) def from_timestamp(stamp,unit):
if unit == "day": return day_from_timestamp(stamp)
if unit == "week": return week_from_timestamp(stamp)
if unit == "month": return month_from_timestamp(stamp)
if unit == "year": return year_from_timestamp(stamp)
d_start = _get_start_of(firstincluded,step)
d_end = _get_start_of(lastincluded,step)
d_start = _get_next(d_start,step,stepn) # first range should end right after the first active scrobbling week / month / whatever relevant step
d_start = _get_next(d_start,step,stepn * trail * -1) # go one range back to begin
def ranges(since=None,to=None,within=None,superrange=None,step="month",stepn=1,trail=1,max_=None):
(firstincluded,lastincluded) = time_stamps(since=since,to=to,within=within,range=superrange)
d_start = from_timestamp(firstincluded,step)
d_start = d_start.next(stepn)
d_start = d_start.next(stepn*trail*-1)
first_range = MRange(d_start,d_start.next(stepn*trail-1))
i = 0 i = 0
d_current = d_start current = d_start
while not _is_past(d_current,d_end) and (max_ is None or i < max_): while current.first_stamp() <= lastincluded and (max_ is None or i < max_):
d_current_end = _get_end(d_current,step,stepn * trail) current_end = current.next(stepn*trail-1)
yield (d_current,d_current_end) yield MRange(current,current_end)
d_current = _get_next(d_current,step,stepn) current = current.next(stepn)
i += 1 i += 1
def _get_start_of(timestamp,unit): #def _get_start_of(timestamp,unit):
date = datetime.datetime.utcfromtimestamp(timestamp) # date = datetime.datetime.utcfromtimestamp(timestamp)
if unit == "year": # if unit == "year":
#return [date.year,1,1] # #return [date.year,1,1]
return [date.year] # return [date.year]
elif unit == "month": # elif unit == "month":
#return [date.year,date.month,1] # #return [date.year,date.month,1]
return [date.year,date.month] # return [date.year,date.month]
elif unit == "day": # elif unit == "day":
return [date.year,date.month,date.day] # return [date.year,date.month,date.day]
elif unit == "week": # elif unit == "week":
change = (date.weekday() + 1) % 7 # change = (date.weekday() + 1) % 7
d = datetime.timedelta(days=change) # d = datetime.timedelta(days=change)
newdate = date - d # newdate = date - d
return [newdate.year,newdate.month,newdate.day] # return [newdate.year,newdate.month,newdate.day]
#
def _get_next(time,unit="auto",step=1): #def _get_next(time,unit="auto",step=1):
result = time[:] # result = time[:]
if unit == "auto": # if unit == "auto":
if is_week(time): unit = "week" # if is_week(time): unit = "week"
# see how long the list is, increment by the last specified unit # # see how long the list is, increment by the last specified unit
else: unit = [None,"year","month","day"][len(time)] # else: unit = [None,"year","month","day"][len(time)]
#while len(time) < 3: # #while len(time) < 3:
# time.append(1) # # time.append(1)
#
if unit == "year": # if unit == "year":
#return [time[0] + step,time[1],time[2]] # #return [time[0] + step,time[1],time[2]]
result[0] += step # result[0] += step
return result # return result
elif unit == "month": # elif unit == "month":
#result = [time[0],time[1] + step,time[2]] # #result = [time[0],time[1] + step,time[2]]
result[1] += step # result[1] += step
while result[1] > 12: # while result[1] > 12:
result[1] -= 12 # result[1] -= 12
result[0] += 1 # result[0] += 1
while result[1] < 1: # while result[1] < 1:
result[1] += 12 # result[1] += 12
result[0] -= 1 # result[0] -= 1
return result # return result
elif unit == "day": # elif unit == "day":
dt = datetime.datetime(time[0],time[1],time[2]) # dt = datetime.datetime(time[0],time[1],time[2])
d = datetime.timedelta(days=step) # d = datetime.timedelta(days=step)
newdate = dt + d # newdate = dt + d
return [newdate.year,newdate.month,newdate.day] # return [newdate.year,newdate.month,newdate.day]
#eugh # #eugh
elif unit == "week": # elif unit == "week":
return _get_next(time,"day",step * 7) # return _get_next(time,"day",step * 7)
#
# like _get_next(), but gets the last INCLUDED day / month whatever # like _get_next(), but gets the last INCLUDED day / month whatever
def _get_end(time,unit="auto",step=1): #def _get_end(time,unit="auto",step=1):
if step == 1: # if step == 1:
if unit == "auto": return time[:] # if unit == "auto": return time[:]
if unit == "year" and len(time) == 1: return time[:] # if unit == "year" and len(time) == 1: return time[:]
if unit == "month" and len(time) == 2: return time[:] # if unit == "month" and len(time) == 2: return time[:]
if unit == "day" and len(time) == 3: return time[:] # if unit == "day" and len(time) == 3: return time[:]
exc = _get_next(time,unit,step) # exc = _get_next(time,unit,step)
inc = _get_next(exc,"auto",-1) # inc = _get_next(exc,"auto",-1)
return inc # return inc
#
#def _is_past(date,limit):
def _is_past(date,limit): # date_, limit_ = date[:], limit[:]
date_, limit_ = date[:], limit[:] # while len(date_) != 3: date_.append(1)
while len(date_) != 3: date_.append(1) # while len(limit_) != 3: limit_.append(1)
while len(limit_) != 3: limit_.append(1) # if not date_[0] == limit_[0]:
if not date_[0] == limit_[0]: # return date_[0] > limit_[0]
return date_[0] > limit_[0] # if not date_[1] == limit_[1]:
if not date_[1] == limit_[1]: # return date_[1] > limit_[1]
return date_[1] > limit_[1] # return (date_[2] > limit_[2])
return (date_[2] > limit_[2]) ##

View File

@ -1,6 +1,6 @@
import urllib import urllib
from bottle import FormsDict from bottle import FormsDict
from malojatime import time_fix, time_str from malojatime import time_fix, time_str, get_range_object
# necessary because urllib.parse.urlencode doesnt handle multidicts # necessary because urllib.parse.urlencode doesnt handle multidicts
@ -59,28 +59,39 @@ def uri_to_internal(keys,forceTrack=False,forceArtist=False):
# 2 # 2
resultkeys2 = {} resultkeys2 = {}
if "since" in keys: resultkeys2["since"] = time_fix(keys.get("since")) # if "since" in keys: resultkeys2["since"] = time_fix(keys.get("since"))
elif "from" in keys: resultkeys2["since"] = time_fix(keys.get("from")) # elif "from" in keys: resultkeys2["since"] = time_fix(keys.get("from"))
elif "start" in keys: resultkeys2["since"] = time_fix(keys.get("start")) # elif "start" in keys: resultkeys2["since"] = time_fix(keys.get("start"))
# # #
if "to" in keys: resultkeys2["to"] = time_fix(keys.get("to")) # if "to" in keys: resultkeys2["to"] = time_fix(keys.get("to"))
elif "until" in keys: resultkeys2["to"] = time_fix(keys.get("until")) # elif "until" in keys: resultkeys2["to"] = time_fix(keys.get("until"))
elif "end" in keys: resultkeys2["to"] = time_fix(keys.get("end")) # elif "end" in keys: resultkeys2["to"] = time_fix(keys.get("end"))
# # #
if "since" in resultkeys2 and "to" in resultkeys2 and resultkeys2["since"] == resultkeys2["to"]: # if "since" in resultkeys2 and "to" in resultkeys2 and resultkeys2["since"] == resultkeys2["to"]:
resultkeys2["within"] = resultkeys2["since"] # resultkeys2["within"] = resultkeys2["since"]
del resultkeys2["since"] # del resultkeys2["since"]
del resultkeys2["to"] # del resultkeys2["to"]
# # #
if "in" in keys: resultkeys2["within"] = time_fix(keys.get("in")) # if "in" in keys: resultkeys2["within"] = time_fix(keys.get("in"))
elif "within" in keys: resultkeys2["within"] = time_fix(keys.get("within")) # elif "within" in keys: resultkeys2["within"] = time_fix(keys.get("within"))
elif "during" in keys: resultkeys2["within"] = time_fix(keys.get("during")) # elif "during" in keys: resultkeys2["within"] = time_fix(keys.get("during"))
if "within" in resultkeys2: # if "within" in resultkeys2:
if "since" in resultkeys2: # if "since" in resultkeys2:
del resultkeys2["since"] # del resultkeys2["since"]
if "to" in resultkeys2: # if "to" in resultkeys2:
del resultkeys2["to"] # del resultkeys2["to"]
since,to,within = None,None,None
if "since" in keys: since = keys.get("since")
elif "from" in keys: since = keys.get("from")
elif "start" in keys: since = keys.get("start")
if "to" in keys: to = keys.get("to")
elif "until" in keys: to = keys.get("until")
elif "end" in keys: to = keys.get("end")
if "in" in keys: within = keys.get("in")
elif "within" in keys: within = keys.get("within")
elif "during" in keys: within = keys.get("during")
resultkeys2["timerange"] = get_range_object(since=since,to=to,within=within)
print(resultkeys2["timerange"].desc())
#3 #3
resultkeys3 = {} resultkeys3 = {}
@ -94,6 +105,7 @@ def uri_to_internal(keys,forceTrack=False,forceArtist=False):
resultkeys4 = {} resultkeys4 = {}
if "max" in keys: resultkeys4["max_"] = int(keys["max"]) if "max" in keys: resultkeys4["max_"] = int(keys["max"])
return resultkeys1, resultkeys2, resultkeys3, resultkeys4 return resultkeys1, resultkeys2, resultkeys3, resultkeys4
def internal_to_uri(keys): def internal_to_uri(keys):
@ -109,7 +121,11 @@ def internal_to_uri(keys):
urikeys.append("title",keys["track"]["title"]) urikeys.append("title",keys["track"]["title"])
#time #time
if "within" in keys: if "range" in keys:
keydict = keys["range"].urikeys()
for k in keydict:
urikeys.append(k,keydict[k])
elif "within" in keys:
urikeys.append("in",time_str(keys["within"])) urikeys.append("in",time_str(keys["within"]))
else: else:
if "since" in keys: if "since" in keys:

View File

@ -10,7 +10,7 @@ def instructions(keys):
_, timekeys, _, amountkeys = uri_to_internal(keys) _, timekeys, _, amountkeys = uri_to_internal(keys)
limitstring = range_desc(**timekeys) limitstring = timekeys["timerange"].desc(prefix=True)
html_filterselector = module_filterselection(keys) html_filterselector = module_filterselection(keys)

View File

@ -26,7 +26,7 @@ def instructions(keys):
else: else:
imgurl = "" imgurl = ""
limitstring += " " + range_desc(**timekeys) limitstring += " " + timekeys["timerange"].desc(prefix=True)
pushresources = [{"file":imgurl,"type":"image"}] if imgurl.startswith("/") else [] pushresources = [{"file":imgurl,"type":"image"}] if imgurl.startswith("/") else []

View File

@ -24,7 +24,7 @@ def instructions(keys):
#limitkey["artist"], limitkey["associated"] = keys.get("artist"), (keys.get("associated")!=None) #limitkey["artist"], limitkey["associated"] = keys.get("artist"), (keys.get("associated")!=None)
limitstring += "of " + artistLink(filterkeys.get("artist")) limitstring += "of " + artistLink(filterkeys.get("artist"))
limitstring += " " + range_desc(**timekeys) limitstring += " " + timekeys["timerange"].desc(prefix=True)
delimitstring = delimit_desc(**delimitkeys) delimitstring = delimit_desc(**delimitkeys)

View File

@ -29,7 +29,7 @@ def instructions(keys):
if moreartists != []: if moreartists != []:
limitstring += " <span class='extra'>including " + artistLinks(moreartists) + "</span>" limitstring += " <span class='extra'>including " + artistLinks(moreartists) + "</span>"
limitstring += " " + range_desc(**timekeys) limitstring += " " + timekeys["timerange"].desc(prefix=True)
delimitstring = delimit_desc(**delimitkeys) delimitstring = delimit_desc(**delimitkeys)

View File

@ -26,7 +26,7 @@ def instructions(keys):
if moreartists != []: if moreartists != []:
limitstring += " <span class='extra'>including " + artistLinks(moreartists) + "</span>" limitstring += " <span class='extra'>including " + artistLinks(moreartists) + "</span>"
limitstring += " " + range_desc(**timekeys) limitstring += " " + timekeys["timerange"].desc(prefix=True)
html_filterselector = module_filterselection(keys) html_filterselector = module_filterselection(keys)

View File

@ -26,7 +26,7 @@ def instructions(keys):
else: else:
imgurl = "" imgurl = ""
limitstring += " " + range_desc(**timekeys) limitstring += " " + timekeys["timerange"].desc(prefix=True)
pushresources = [{"file":imgurl,"type":"image"}] if imgurl.startswith("/") else [] pushresources = [{"file":imgurl,"type":"image"}] if imgurl.startswith("/") else []

View File

@ -26,7 +26,7 @@ def instructions(keys):
else: else:
imgurl = "" imgurl = ""
limitstring += " " + range_desc(**timekeys) limitstring += " " + timekeys["timerange"].desc(prefix=True)
pushresources = [{"file":imgurl,"type":"image"}] if imgurl.startswith("/") else [] pushresources = [{"file":imgurl,"type":"image"}] if imgurl.startswith("/") else []