def __init__(self, country="US"): try: holidays.country_holidays(country=country) except NotImplementedError: available_countries = ( "https://github.com/dr-prodigy/python-holidays#available-countries" ) error = "must be one of the available countries:\n%s" % available_countries raise ValueError(error) self.federal_holidays = getattr(holidays, country)(years=range(1950, 2100))
def standard_holidays( year, country="US", subdiv="MA", add_holidays=None, remove_holidays=None ) -> dict: # 1. Get standard holidays from python's holidays module countr_holidays = [] countr_holidays = holidays.country_holidays( country=country, subdiv=subdiv, years=year ) # 2. Remove known obsolete holidays if country == "US" and subdiv == "MA": countr_holidays.pop_named("Evacuation Day") # 3. Remove user specified holidays if remove_holidays: for record in remove_holidays: countr_holidays.pop_named(record) # 4. Append user defined holidays if add_holidays: for k, v in add_holidays.items(): # Attach the given year to the key key = f"{year}-{k}" countr_holidays[key] = v return countr_holidays
def celebrate() -> str: """Function to look if the current date is a holiday or a birthday. Returns: str: A string of the event observed today. """ day = datetime.today().date() us_holidays = country_holidays("US").get(day) # checks if the current date is a US holiday in_holidays = country_holidays("IND", prov="TN", state="TN").get(day) # checks if Indian (esp TN) holiday if in_holidays: return in_holidays elif us_holidays and "Observed" not in us_holidays: return us_holidays elif env.birthday == datetime.now().strftime("%d-%B"): return "Birthday"
def __init__(self, country="US"): self.country = country try: self.holidays = holidays.country_holidays(country=self.country) except NotImplementedError: available_countries = ( "https://github.com/dr-prodigy/python-holidays#available-countries" ) error = "must be one of the available countries:\n%s" % available_countries raise ValueError(error) years_list = [1950 + x for x in range(150)] self.federal_holidays = getattr(holidays, country)(years=years_list)
def is_not_holiday(date, country_code) -> bool: try: holidays_list = country_holidays(country_code.upper()) if isinstance(date, str): d = parse(date) else: d = date except Exception as e: return False if d in holidays_list: return False else: return True
def get_typical_days(weather_data, cfg): """Run VDI 4655 - Step 1. Determine the "typtag" key for each timestep (). For the full "typtag", we need to identify: - Season - Workdays, Sundays and public holidays - Cloud cover amount """ settings = cfg['settings'] # Flag to determine if any holidays have been found: interpolation_freq = pd.Timedelta(settings['intervall']) flag_holidays_found = False # --- Season -------------------------------------------------------------- # The 'season' (transition, summer or winter) is defined by the daily # average of the ambient temperature. # Resample ambient temperatures in DataFrame to days and take mean tamb_avg_list = weather_data['TAMB'].resample('D', label='right', closed='right').mean() # Write the daily mean values to all original time steps tamb_avg_list = tamb_avg_list.reindex(weather_data.index) tamb_avg_list.fillna(method='backfill', inplace=True) season_list = [] # The VDI 4655 default heat limit is 15°C (definition of summer days). # For low- and zero-energy houses, the average daily temperatures have # to be adapted to the actual conditions. (see VDI 4655, page 15) Tamb_heat_limit = settings.get('Tamb_heat_limit', 15) # °C # Read through list of temperatures line by line and apply the definition for tamb_avg in tamb_avg_list: if tamb_avg < 5: season_list.append('W') # Winter elif tamb_avg > Tamb_heat_limit: season_list.append('S') # Summer else: season_list.append('U') # Übergang (Transition) # Alternative season determination method: # From 'BDEW Standardlastprofile': season_list_BDEW = get_season_list_BDEW(weather_data) # Save the results in the weather_data DataFrame weather_data['TAMB_d'] = tamb_avg_list if settings.get('use_BDEW_seasons', False) is False: weather_data['season'] = season_list elif settings.get('use_BDEW_seasons', False) is True: weather_data['season'] = season_list_BDEW weather_data['season'].replace(to_replace={ 'Winter': 'W', 'Sommer': 'S', 'Übergangszeit': 'U' }, inplace=True) # Store the BDEW seasons separately weather_data['season_BDEW'] = season_list_BDEW steps_per_day = 24 / (interpolation_freq.seconds / 3600.0) settings['steps_per_day'] = steps_per_day logger.debug('Number of days in winter: ' + str(season_list.count('W') / steps_per_day)) logger.debug('Number of days in summer: ' + str(season_list.count('S') / steps_per_day)) logger.debug('Number of days in transition: ' + str(season_list.count('U') / steps_per_day)) # Use https://pypi.org/project/holidays/ for holiday-detection used_holidays = [] if settings.get('holidays'): country = settings['holidays'].get('country', 'DE') province = settings['holidays'].get('province', None) used_holidays = holidays.country_holidays(country, subdiv=province) # Read through list of days line by line and see what kind of day they are. # Problem: In the weather data, the bins are labeled on the 'right' # (Each time stamp describes the interval before). Therefore the time stamp # midnight (00:00:00) describes the last interval of the day before. # However, asking for the weekday of a midnight time stamp gives the name # of the next day. Thus the resulting list of weekdays is shifted by one # time step. weekdays_list = [] weekdays_list_BDEW = [] for date_obj in weather_data.index: if date_obj.dayofweek == 6: # 6 equals Sunday weekdays_list.append('S') weekdays_list_BDEW.append('Sonntag') elif date_obj in used_holidays: weekdays_list.append('S') weekdays_list_BDEW.append('Sonntag') flag_holidays_found = True elif date_obj.dayofweek == 5: # 5 equals Saturday weekdays_list.append('W') weekdays_list_BDEW.append('Samstag') else: weekdays_list.append('W') weekdays_list_BDEW.append('Werktag') # Solution to problem: We take the first list entry, then add the rest of # the list minus the very last entry. weather_data['weekday'] = [weekdays_list[0]] + weekdays_list[:-1] weather_data['weekday_BDEW'] = [weekdays_list_BDEW[0]] + \ weekdays_list_BDEW[:-1] # Print a warning, if necessary if flag_holidays_found is False: logger.warning('Warning! No holidays were found for the chosen time!') # --- Cloud cover amount -------------------------------------------------- ccover_avg_list = weather_data['CCOVER'].resample('D', label='right', closed='right').mean() ccover_avg_list = ccover_avg_list.reindex(weather_data.index) ccover_avg_list.fillna(method='backfill', inplace=True) # The interpolation to 15min may cause a slight difference of daily means # compared to 60min, in rare cases shifting from >5.0 to <5.0. # Rounding to the first decimal place may prevent this issue. ccover_avg_list = ccover_avg_list.round(decimals=1) # Read through list of cloud cover line by line and apply the definition cloudy_list = [] for ccover_avg in ccover_avg_list: if (ccover_avg < 5.0): cloudy_list.append('H') else: cloudy_list.append('B') weather_data['cloudy'] = cloudy_list # Combine the gathered information from season, weekday and cloudyness # into one 'typtag' key weather_data['typtag'] = weather_data['season'] + \ weather_data['weekday'] + weather_data['cloudy'] # For summer days, the VDI 4655 makes no distinction in terms of cloud # amount. So we need to replace 'heiter' and 'bewölkt' with 'X' typtage_replace = { 'typtag': { 'SWH': 'SWX', 'SWB': 'SWX', 'SSH': 'SSX', 'SSB': 'SSX' } } weather_data.replace(to_replace=typtage_replace, inplace=True)
def __init__(self, date_column: str, hour_column: str, country: str, subdiv: str = None): self.holidays = holidays.country_holidays(country, subdiv=subdiv) self.date_column = date_column self.hour_column = hour_column