'Determine season given timestamp in Python using datetime

I'd like to extract only the month and day from a timestamp using the datetime module (not time) and then determine if it falls within a given season (fall, summer, winter, spring) based on the fixed dates of the solstices and equinoxes.

For instance, if the date falls between March 21 and June 20, it is spring. Regardless of the year. I want it to just look at the month and day and ignore the year in this calculation.

I've been running into trouble using this because the month is not being extracted properly from my data, for this reason.



Solution 1:[1]

It might be easier just to use the day of year parameter. It's not much different than your approach, but possibly easier to understand than the magic numbers.

# get the current day of the year
doy = datetime.today().timetuple().tm_yday

# "day of year" ranges for the northern hemisphere
spring = range(80, 172)
summer = range(172, 264)
fall = range(264, 355)
# winter = everything else

if doy in spring:
  season = 'spring'
elif doy in summer:
  season = 'summer'
elif doy in fall:
  season = 'fall'
else:
  season = 'winter'

Solution 2:[2]

I came here looking how to map dates to seasons, and based on this answer I finally solved it in the following way:

def season_of_date(date):
    year = str(date.year)
    seasons = {'spring': pd.date_range(start='21/03/'+year, end='20/06/'+year),
               'summer': pd.date_range(start='21/06/'+year, end='22/09/'+year),
               'autumn': pd.date_range(start='23/09/'+year, end='20/12/'+year)}
    if date in seasons['spring']:
        return 'spring'
    if date in seasons['summer']:
        return 'summer'
    if date in seasons['autumn']:
        return 'autumn'
    else:
        return 'winter'

# Assuming df has a date column of type `datetime`
df['season'] = df.date.map(season_of_date)

So in principle it works for any year, given a datetime.

Solution 3:[3]

The hemisphere that you are in must be taken into account. You must determine the hemisphere using geolocation yourself.

def season(self, HEMISPHERE):
    date = self.now()
    md = date.month * 100 + date.day

    if ((md > 320) and (md < 621)):
        s = 0 #spring
    elif ((md > 620) and (md < 923)):
        s = 1 #summer
    elif ((md > 922) and (md < 1223)):
        s = 2 #fall
    else:
        s = 3 #winter

    if not HEMISPHERE == 'north':
        s = (s + 2) % 3
    return s

Solution 4:[4]

I'm too new to comment, and my edit was rejected, so here is corrected code for @adsf reponse.

def season(date, hemisphere):
    ''' date is a datetime object
        hemisphere is either 'north' or 'south', dependent on long/lat.
    '''
    md = date.month * 100 + date.day

    if ((md > 320) and (md < 621)):
        s = 0 #spring
    elif ((md > 620) and (md < 923)):
        s = 1 #summer
    elif ((md > 922) and (md < 1223)):
        s = 2 #fall
    else:
        s = 3 #winter

    if hemisphere != 'north':
        if s < 2:
            s += 2 
        else:
            s -= 2

    return s

Solution 5:[5]

I think you can use pandas.Series.dt.quarter? For example,

datetime = pd.Series(pd.to_datetime(['2010-09-30', '2010-04-25', '2010-01-25', '2010-10-29', '2010-12-25']))
seasons = datetime.dt.quarter

seasons:
0    3
1    2
2    1
3    4
4    4

seasons would be what you want?

Solution 6:[6]

This is how I finally solved it. I doubt this is the best solution, but it works. Feel free to offer better solutions.

import datetime

def get_season(date):
    """
    convert date to month and day as integer (md), e.g. 4/21 = 421, 11/17 = 1117, etc.
    """
    m = date.month * 100
    d = date.day
    md = m + d

    if ((md >= 301) and (md <= 531)):
        s = 0  # spring
    elif ((md > 531) and (md < 901)):
        s = 1  # summer
    elif ((md >= 901) and (md <= 1130)):
        s = 2  # fall
    elif ((md > 1130) and (md <= 0229)):
        s = 3  # winter
    else:
        raise IndexError("Invalid date")

    return s

season = get_season(dt.date())

Solution 7:[7]

This is what i normally use:

seasons = {'Summer':(datetime(2014,6,21), datetime(2014,9,22)),
           'Autumn':(datetime(2014,9,23), datetime(2014,12,20)),
           'Spring':(datetime(2014,3,21), datetime(2014,6,20))}

def get_season(date):
    for season,(season_start, season_end) in seasons.items():
        if date>=season_start and date<= season_end:
            return season
    else:
        return 'Winter'

Solution 8:[8]

using python datetime and simple dictionary

import datetime
date = datetime.datetime.strptime('01/05/2015 01:30:00 PM', "%m/%d/%Y %H:%M:%S %p")

//using above created date for the code below
seasons = {1:[12,1,2],2:[3,4,5],3:[6,7,8],4:[9,10,11]}
ss={}
for k,v in seasons.items():
    for e in v:
        ss[e] = k
print(ss[date.month])

Solution 9:[9]

There is no need to deal with years, it is enough to compare the month and day as tuples like this:

import datetime


def get_season(date: datetime.datetime, north_hemisphere: bool = True) -> str:
    now = (date.month, date.day)
    if (3, 21) <= now < (6, 21):
        season = 'spring' if north_hemisphere else 'fall'
    elif (6, 21) <= now < (9, 21):
        season = 'summer' if north_hemisphere else 'winter'
    elif (9, 21) <= now < (12, 21):
        season = 'fall' if north_hemisphere else 'spring'
    else:
        season = 'winter' if north_hemisphere else 'summer'

    return season

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jheddings
Solution 2 iipr
Solution 3 Paul H
Solution 4 David Bianco
Solution 5 Jing Li
Solution 6
Solution 7 Manuel G
Solution 8 Bharath Bandaru
Solution 9 Mauro Schilman