I have the following tuples of month,day
stored in the dictionary seasons
:
seasons = {
'S1': (
((1, 10),(5, 31))
),
'S2': (
((9, 1),(1, 9))
),
'S3': (
((6, 1),(9, 30))
)
}
I want to check in which date interval a datetime dt
is located and assign the name S1
, S2
or S3
, accordingly.
I tried to do it this way, but start
and end
seem to be numbers instead of tuples.
def getSeason(dt):
season = None
for t, ranges in seasons.items():
for start, end in ranges:
if date(dt.year,start(0),start(1)) <= dt.date() <= date(dt.year,end(0),end(1)):
season = t
break
if season is not None:
break
return season
Few issues, i see with your code -
You seem to be assuming you have a tuple of tuple of tuples, but you actually have a tuple of tupe, because when you try to make a tuple of one element, you need to follow the element by a ,
, otherwise python will interpret it as brackets used for grouping. Example -
a = ((1,2),)
In simple case,
a = (1,)
Secondly, when accessing a tuple value, you should use start[0]
, not start(0)
, as the latter is trying to call it as a function, with 0
as parameter.
Your logic does not consider the case where the season start is in one year, whereas the season end is in the next year.
So seasons would look like -
seasons = {
'S1': (
((1, 10),(5, 31)),
),
'S2': (
((9, 1),(1, 9)),
),
'S3': (
((6, 1),(9, 30)),
)
}
A small change to your original getSeason()
function, to make your case work -
def getSeason(dt):
season = None
for t, ranges in seasons.items():
for start, end in ranges:
if start[0] <= end[0] or (start[0] == end[0] and start[1] <= end[1]):
if date(dt.year,start[0],start[1]) <= dt.date() <= date(dt.year,end[0],end[1]):
season = t
break
else:
if (date(dt.year,start[0],start[1]) <= dt.date() <= date(dt.year+1,end[0],end[1])) or (date(dt.year-1,start[0],start[1]) <= dt.date() <= date(dt.year,end[0],end[1])):
season = t
break
if season is not None:
break
return season
The above would work, but you don't really need a tuple of tuple of tuples for your use case, you can change the logic in your getSeasons()
function to use a tuple of tuple .
The main problem is that you're unpacking the tuple thus getting an int
into start
and end
. if you remove the nested loop your code will work as you expect:
from datetime import datetime
seasons = {
'S1': (
(1, 10), (5, 31),
),
'S2': (
(9, 1), (1, 9),
),
'S3': (
(6, 1), (9, 30),
)
}
def getSeason(dt):
for t, (start, end) in seasons.iteritems():
if start[0] < end[0] and datetime(dt.year, start[0], start[1]) <= dt <= datetime(dt.year, end[0], end[1]):
return t
elif (start[0] > end[0] and
(datetime(dt.year, start[0], start[1]) <= dt <= datetime(dt.year + 1, end[0], end[1]) or
datetime(dt.year - 1, start[0], start[1]) <= dt <= datetime(dt.year, end[0], end[1]))):
return t
else:
continue
return None
Try the following:
from datetime import date
seasons = {
'S1': (
((1, 10),(5, 31))
),
'S2': (
((9, 1),(1, 9))
),
'S3': (
((6, 1),(9, 30))
)
}
def getSeason(dt):
for sname, duration in seasons.items():
start, end = duration
start_date = date(dt.year, start[0], start[1])
end_date = date(dt.year, end[0], end[1])
if dt < start_date:
start_date = date(start_date.year - 1, start_date.month, start_date.day)
end_date = date(end_date.year - 1, end_date.month, end_date.day)
if end_date < start_date:
end_date = date(end_date.year+1, end_date.month, end_date.day)
if start_date <= dt <= end_date:
return sname
return None
if __name__ == '__main__':
s = getSeason(date(1921, 5, 24))
print s
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.