Module crepyscule_summer_time
[hide private]
[frames] | no frames]

Source Code for Module crepyscule_summer_time

  1  #!/usr/bin/env python 
  2  # -*- coding: iso-8859-1 -*- 
  3   
  4  # Copyright 2005,2008  Miguel Tremblay 
  5   
  6  # This program is free software; you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation; either version 3 of the License, or 
  9  # (at your option) any later version. 
 10   
 11  # This program is distributed in the hope that it will be useful, 
 12  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  # GNU General Public License for more details. 
 15   
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not see  <http://www.gnu.org/licenses/>. 
 18  ############################################################################ 
 19   
 20  """ 
 21  Adjust the sunset and sunrise hour depending on the timezone. 
 22  The list of timezone (lTimezone) is based on software kstars 
 23  of the kdeedu project (http://edu.kde.org/kstars/). 
 24  The original file contains informations by column like this: 
 25  city : province : country : Lat_deg : Lat_min : Lat_sec : N|S : 
 26  Lon_deg : Lon_min : Lon_sec : E|W : UTC_difference : two_letters[??] 
 27                 
 28  Project home page is U{http://ptaff.ca/crepyscule/} 
 29   
 30   - Name: crepyscule_summer_time.py 
 31   - Author:      U{Miguel Tremblay<http://ptaff.ca/miguel/>} 
 32   - Date:        January 15th  2005 
 33           
 34  """           
 35                  
 36  import time 
 37  import calendar 
 38   
 39  import numpy 
 40   
 41  lTimezone = ('IR', 'JD', 'EU', 'IQ', 'US', 'CH', 'EG', \ 
 42                 'MX', 'SK', 'HK', 'NB', 'FK', 'PY', 'NZ', \ 
 43                 'TS', 'BZ', 'CL', 'AU', 'TG', 'ZN', 'LB', \ 
 44                 'SY', 'RU') 
 45  dMonth = { 'JAN': 1, 
 46             'FEB': 2, 
 47             'MAR': 3, 
 48             'APR': 4, 
 49             'MAY': 5, 
 50             'JUN': 6, 
 51             'JUL': 7, 
 52             'AUG': 8, 
 53             'SEP': 9, 
 54             'OCT': 10, 
 55             'NOV': 11, 
 56             'DEC': 12} 
 57  dWeek = { 'MON': 0, 
 58            'TUE': 1, 
 59            'WED': 2, 
 60            'THU': 3, 
 61            'FRI': 4, 
 62            'SAT': 5, 
 63            'SUN': 6 } 
 64   
 65  # Optimization. Populate this list when as summertime start,end is asked 
 66  #  for a specific year. Format is dYearSummertime{'year' : dCode} and 
 67  #  dCode is in the format dCode{ 'code' , [nStart, nEnd]} 
 68  dYearSummertime = {} 
 69   
70 -def get_summer_time_days(sSummerCode, nYear):
71 """ 72 Return in julian day the beginning of daylight time 73 and the end of daylight time. 74 75 @type sSummerCode: string 76 @param sSummerCode: summer time two letters code 77 @type nYear: int 78 @param nYear: Year to retrieve the dates for this summer code. Might 79 have an effect in the case of 'US' since it had been change in 2007. 80 @rtype: tuple 81 @return: First and last julian day for this summer time code 82 """ 83 sYear = str(nYear) 84 85 # I know, it is not beautiful. No can do. 86 if sSummerCode == 'IR': 87 # Start: March 21 88 nDayStart = __get_julian(sYear+'-03-21') 89 # End: September 22 90 nDayEnd = __get_julian(sYear+'-09-22') 91 elif sSummerCode == 'JD': 92 # Start: March last Thursday 93 nWeekdayStart = __get_day('last', 'THU', 'MAR', nYear) 94 nDayStart = __get_julian(sYear+'-03-'+str(nWeekdayStart)) 95 # End: Sep's last Thu 96 nWeekdayEnd = __get_day('last', 'THU', 'SEP', nYear) 97 nDayEnd = __get_julian(sYear+'-09-'+str(nWeekdayEnd)) 98 elif sSummerCode == 'EU'or sSummerCode == 'RU': 99 # Start: March last Sunday 100 nWeekdayStart = __get_day('last', 'SUN', 'MAR', nYear) 101 nDayStart = __get_julian(sYear+'-03-'+str(nWeekdayStart)) 102 # End: Oct's last Sunday 103 nWeekdayEnd = __get_day('last', 'SUN', 'OCT', nYear) 104 nDayEnd = __get_julian(sYear+'-10-'+str(nWeekdayEnd)) 105 elif sSummerCode == 'IQ' or sSummerCode == 'SY': 106 # Start: April 1st 107 nDayStart = __get_julian(sYear+'-04-01') 108 # End: October 1st 109 nDayEnd = __get_julian(sYear+'-10-01') 110 elif sSummerCode == 'US': 111 # Starting 2007, summer time has a new definition: 112 if nYear < 2007: 113 # Start: April 1st Sunday 114 nWeekdayStart = __get_day('first', 'SUN', 'APR', nYear) 115 nDayStart = __get_julian(sYear+'-04-'+str(nWeekdayStart)) 116 # End: Oct's last Sunday 117 nWeekdayEnd = __get_day('last', 'SUN', 'OCT', nYear) 118 nDayEnd = __get_julian(sYear+'-10-'+str(nWeekdayEnd)) 119 else: 120 # Start: March 2nd Sunday 121 nWeekdayStart = __get_day('second', 'SUN', 'MAR', nYear) 122 nDayStart = __get_julian(sYear+'-03-'+str(nWeekdayStart)) 123 # End: November first Sunday 124 nWeekdayEnd = __get_day('first', 'SUN', 'NOV', nYear) 125 nDayEnd = __get_julian(sYear+'-11-'+str(nWeekdayEnd)) 126 elif sSummerCode == 'CH': 127 # Start: April 2nd Sunday 128 nWeekdayStart = __get_day('second', 'SUN', 'APR', nYear) 129 nDayStart = __get_julian(sYear+'-04-'+str(nWeekdayStart)) 130 # End: September 2nd Sunday 131 nWeekdayEnd = __get_day('second', 'SUN', 'SEP', nYear) 132 nDayEnd = __get_julian(sYear+'-09-'+str(nWeekdayEnd)) 133 elif sSummerCode == 'EG': 134 # Start: April last Friday 135 nWeekdayStart = __get_day('last', 'FRI', 'APR', nYear) 136 nDayStart = __get_julian(sYear+'-04-'+str(nWeekdayStart)) 137 # End: September last Thursday 138 nWeekdayEnd = __get_day('last', 'THU', 'SEP', nYear) 139 nDayEnd = __get_julian(sYear+'-09-'+str(nWeekdayEnd)) 140 elif sSummerCode == 'MX': 141 # Start: April 1st Sunday 142 nWeekdayStart = __get_day('first', 'SUN', 'APR', nYear) 143 nDayStart = __get_julian(sYear+'-04-'+str(nWeekdayStart)) 144 # End: Sep's last Sun 145 nWeekdayEnd = __get_day('last', 'SUN', 'SEP', nYear) 146 nDayEnd = __get_julian(sYear+'-09-'+str(nWeekdayEnd)) 147 elif sSummerCode == 'SK': 148 # Start: May 2nd Sunday 149 nWeekdayStart = __get_day('second', 'SUN', 'MAR', nYear) 150 nDayStart = __get_julian(sYear+'-05-'+str(nWeekdayStart)) 151 # End: October 2nd Sunday 152 nWeekdayEnd = __get_day('second', 'SUN', 'OCT', nYear) 153 nDayEnd = __get_julian(sYear+'-10-'+str(nWeekdayEnd)) 154 elif sSummerCode == 'HK': 155 # Start: May 2nd Sunday 156 nWeekdayStart = __get_day('second', 'SUN', 'MAR', nYear) 157 nDayStart = __get_julian(sYear+'-05-'+str(nWeekdayStart)) 158 # End: October 3rd Sunday 159 nWeekdayEnd = __get_day('third', 'SUN', 'OCT', nYear) 160 nDayEnd = __get_julian(sYear+'-10-'+str(nWeekdayEnd)) 161 elif sSummerCode == 'NB': 162 # Start: September 1st Sunday 163 nWeekdayStart = __get_day('first', 'SUN', 'SEP', nYear) 164 nDayStart = __get_julian(sYear+'-09-'+str(nWeekdayStart)) 165 # End: April 1st Sunday 166 nWeekdayEnd = __get_day('first', 'SUN', 'APR', nYear) 167 nDayEnd = __get_julian(sYear+'-04-'+str(nWeekdayEnd)) 168 elif sSummerCode == 'FK': 169 # Start: September 1st Sunday 170 nWeekdayStart = __get_day('first', 'SUN', 'SEP', nYear) 171 nDayStart = __get_julian(sYear+'-09-'+str(nWeekdayStart)) 172 # End: April 3rd Sunday 173 nWeekdayEnd = __get_day('third', 'SUN', 'APR', nYear) 174 nDayEnd = __get_julian(sYear+'-04-'+str(nWeekdayEnd)) 175 elif sSummerCode == 'PY': 176 # Start: October 1st Sunday 177 nWeekdayStart = __get_day('first', 'SUN', 'OCT', nYear) 178 nDayStart = __get_julian(sYear+'-10-'+str(nWeekdayStart)) 179 # End: March 1st Sunday 180 nWeekdayEnd = __get_day('first', 'SUN', 'MAR', nYear) 181 nDayEnd = __get_julian(sYear+'-03-'+str(nWeekdayEnd)) 182 elif sSummerCode == 'NZ': 183 # Start: October 1st Sunday 184 nWeekdayStart = __get_day('first', 'SUN', 'OCT', nYear) 185 nDayStart = __get_julian(sYear+'-10-'+str(nWeekdayStart)) 186 # End: March 3rd Sun 187 nWeekdayEnd = __get_day('third', 'SUN', 'MAR', nYear) 188 nDayEnd = __get_julian(sYear+'-03-'+str(nWeekdayEnd)) 189 elif sSummerCode == 'TS': 190 # Start: October 1st Sunday 191 nWeekdayStart = __get_day('first', 'SUN', 'OCT', nYear) 192 nDayStart = __get_julian(sYear+'-10-'+str(nWeekdayStart)) 193 # End: March last sunday 194 nWeekdayEnd = __get_day('last', 'SUN', 'MAR', nYear) 195 nDayEnd = __get_julian(sYear+'-03-'+str(nWeekdayEnd)) 196 elif sSummerCode == 'BZ': 197 # Start: October 2nd Sunday 198 nWeekdayStart = __get_day('second', 'SUN', 'OCT', nYear) 199 nDayStart = __get_julian(sYear+'-10-'+str(nWeekdayStart)) 200 # End: February 3rd sunday 201 nWeekdayEnd = __get_day('third', 'SUN', 'FEB', nYear) 202 nDayEnd = __get_julian(sYear+'-02-'+str(nWeekdayEnd)) 203 elif sSummerCode == 'CL': 204 # Start: October 2nd Sunday 205 nWeekdayStart = __get_day('second', 'SUN', 'OCT', nYear) 206 nDayStart = __get_julian(sYear+'-10-'+str(nWeekdayStart)) 207 # End: March 2nd sunday 208 nWeekdayEnd = __get_day('second', 'SUN', 'MAR', nYear) 209 nDayEnd = __get_julian(sYear+'-03-'+str(nWeekdayEnd)) 210 elif sSummerCode == 'AU': 211 # Start: October last Sunday 212 nWeekdayStart = __get_day('last', 'SUN', 'OCT', nYear) 213 nDayStart = __get_julian(sYear+'-10-'+str(nWeekdayStart)) 214 # End: March last Sunday 215 nWeekdayEnd = __get_day('last', 'SUN', 'MAR', nYear) 216 nDayEnd = __get_julian(sYear+'-03-'+str(nWeekdayEnd)) 217 elif sSummerCode == 'TG': 218 # Start: November 1st Sunday 219 nWeekdayStart = __get_day('first', 'SUN', 'NOV', nYear) 220 nDayStart = __get_julian(sYear+'-11-'+str(nWeekdayStart)) 221 # End: January last Sunday 222 nWeekdayEnd = __get_day('last', 'SUN', 'JAN', nYear) 223 nDayEnd = __get_julian(sYear+'-01-'+str(nWeekdayEnd)) 224 elif sSummerCode == 'ZN': 225 # Start: First Friday in April 226 nWeekdayStart = __get_day('first', 'FRI', 'APR', nYear) 227 nDayStart = __get_julian(sYear+'-04-'+str(nWeekdayStart)) 228 # End: First Friday in September 229 nWeekdayEnd = __get_day('first', 'FRI', 'SEP', nYear) 230 nDayEnd = __get_julian(sYear+'-09-'+str(nWeekdayEnd)) 231 elif sSummerCode == 'LB': 232 # Start: Last Sunday in March 233 nWeekdayStart = __get_day('last', 'SUN', 'MAR', nYear) 234 nDayStart = __get_julian(sYear+'-03-'+str(nWeekdayStart)) 235 # End: Last Sunday in October 236 nWeekdayEnd = __get_day('last', 'SUN', 'OCT', nYear) 237 nDayEnd = __get_julian(sYear+'-10-'+str(nWeekdayEnd)) 238 elif sSummerCode == "--" or sSummerCode == "": 239 nDayStart = 366 240 nDayEnd = 0 241 else: 242 SUMMER_TIME_ERROR = 'This time zone does not exist:%s' % (sSummerCode) 243 raise SUMMER_TIME_ERROR 244 245 246 return (nDayStart, nDayEnd)
247
248 -def __get_day(sPosition, sDay, sMonth, nYear):
249 """ 250 Get the day of the month corresponding to the position in the month. 251 Eg: First monday of april would be __get_day('first', 'MON', 'APR') 252 253 @type sPosition: string 254 @param sPosition: Value in ['first', 'second', 'third', 'last'] 255 @type sDay: string 256 @param sDay: Day of the week. See L{dWeek} for possible value of string. 257 @type sMonth: string 258 @param sMonth: Month of the date. See L{dMonth} for possible value of 259 string. 260 @type nYear: int 261 @param nYear: Year of which to retrieve the julian day. 262 263 @rtype: int 264 @return: Julian day of the year for this date. 265 """ 266 # First day of. 267 llMonth = calendar.monthcalendar(nYear, dMonth[sMonth]) 268 # First 269 if sPosition == 'first' : 270 lWeek = llMonth[0] 271 if lWeek[dWeek[sDay]] == 0: 272 lWeek = llMonth[1] 273 nDay = lWeek[dWeek[sDay]] 274 # Second 275 elif sPosition == 'second': 276 lWeek = llMonth[1] 277 if llMonth[0][dWeek[sDay]] == 0: 278 lWeek = llMonth[2] 279 nDay = lWeek[dWeek[sDay]] 280 # Third 281 elif sPosition == 'third': 282 lWeek = llMonth[2] 283 if llMonth[0][dWeek[sDay]] == 0: 284 lWeek = llMonth[3] 285 nDay = lWeek[dWeek[sDay]] 286 # Last 287 elif sPosition == 'last': 288 lWeek = llMonth[len(llMonth)-1] 289 if lWeek[dWeek[sDay]] == 0: 290 lWeek = llMonth[len(llMonth)-2] 291 nDay = lWeek[dWeek[sDay]] 292 293 return nDay
294 295 296
297 -def __get_julian(sDate):
298 """ 299 Return julian day corresponding to iso 8601 date 300 format is YYYY-MM-DD 301 302 @type sDate: string 303 @param sDate: ISO8601 date. Format is YYYY-MM-DD 304 305 @rtype: int 306 @return: Julian day 307 """ 308 tTime = time.strptime(sDate, '%Y-%m-%d') 309 # The indices 7 is the julian day in struct_time 310 return tTime[7]
311 312
313 -def adjust_summer_time(lSunrise, lSunset, sTimezone, nYear):
314 """ 315 Adjust the hour of sunset and sunrise depending of the summer time 316 317 @type lSunrise: list 318 @param lSunrise: List of sunrise for the whole year. 319 @type lSunset: list 320 @param lSunset: List of sunset for the whole year. 321 @type sTimezone: string 322 @param sTimezone: Summer time two letters code 323 @type nYear: int 324 @param nYear: Year to retrieve the dates for this summer code. 325 326 @rtype: list 327 @return: List of the adjusted value of sunrise and sunset: 328 [lSunrise, lSunset] 329 """ 330 tJulian = get_summer_time_days(sTimezone, nYear) 331 332 nStart = tJulian[0] 333 nEnd = tJulian[1] 334 335 # Transform in numpy, less painfull 336 npSunrise = numpy.array(lSunrise) 337 npSunset = numpy.array(lSunset) 338 339 # Northern hemisphere 340 if nStart < nEnd: 341 npSunrise[nStart:nEnd] = npSunrise[nStart:nEnd]+ 1 342 npSunset[nStart:nEnd] = npSunset[nStart:nEnd]+ 1 343 # Southern hemisphere 344 else: 345 npSunrise[0:nEnd] = npSunrise[0:nEnd] + 1 346 npSunrise[nStart:len(npSunrise)] = \ 347 npSunrise[nStart:len(npSunrise)] + 1 348 npSunset[0:nEnd] = npSunset[0:nEnd] + 1 349 npSunset[nStart:len(npSunset)] = \ 350 npSunset[nStart:len(npSunset)] + 1 351 352 return [npSunrise.tolist(), npSunset.tolist(), tJulian]
353
354 -def adjust_summer_time_one_day(tDay, fValue, sTimezone):
355 """ 356 Adjust the hour of sunset and sunrise depending of the summer time 357 for this particular day. 358 359 @type tDay: tuple 360 @param tDay: Tuple of this day in the format (nYear, nMonth, nDay) 361 @type fValue: float 362 @param fValue: sunrise or sunset value to adjust following summertime. 363 364 """ 365 global dYearSummertime 366 367 # Get julian day 368 (nYear, nMonth, nDay) = tDay 369 sDate = str(nYear) + '-' + str(nMonth) + '-' + str(nDay) 370 nJulian = __get_julian(sDate) 371 372 373 # Tcheck if this value have been asked before 374 dCurrent = {} 375 if nYear in dYearSummertime.keys(): 376 dCurrent = dYearSummertime[nYear] 377 378 if sTimezone in dCurrent.keys(): 379 (nStart, nEnd) = dCurrent[sTimezone] 380 else: 381 # Get start and end date for this code 382 tJulian = get_summer_time_days(sTimezone, nYear) 383 nStart = tJulian[0] 384 nEnd = tJulian[1] 385 # Add value in the global dictionary 386 dCurrent[sTimezone] = (nStart, nEnd) 387 dYearSummertime[nYear] = dCurrent 388 389 # Adjust if needed 390 if nJulian > nStart and nJulian < nEnd: 391 fValue = fValue + 1 392 393 return fValue
394 395 396 if __name__ == "__main__": 397 test() 398