2 # -*- coding: koi8-r -*-
5 # opDate - date/time manipulation routines
6 # Some ideas came from Turbo Professional/Object Professional (t/o)pDate.PAS
8 # Written by Broytman, Nov 1997 - Dec 2003
9 # Copyright (C) 1997-2003 PhiloSoft Design
15 from calendar import *
16 from opstring import *
21 MinDate = 0x00000000 # = 01/01/1600
22 MaxDate = 0x000D6025 # = 12/31/3999
23 Date1900 = 0x0001AC05 # = 01/01/1900
24 Date1980 = 0x00021E28 # = 01/01/1980
25 Date2000 = 0x00023AB1 # = 01/01/2000
30 MinTime = 0 # = 00:00:00 am
31 MaxTime = 86399 # = 23:59:59 pm
34 SecondsInDay = 86400 # number of seconds in a day
35 SecondsInHour = 3600 # number of seconds in an hour
36 SecondsInMinute = 60 # number of seconds in a minute
37 HoursInDay = 24 # number of hours in a day
38 MinutesInHour = 60 # number of minutes in an hour
40 First2Months = 59 # 1600 was a leap year
41 FirstDayOfWeek = 5 # 01/01/1600 was a Saturday
45 class opdate_error(Exception):
50 ### Date manipulation routines
54 if ( (Year % 4 == 0) and (Year % 4000 <> 0) and ((Year % 100 <> 0) or (Year % 400 == 0)) ):
63 if Year < Threshold2000:
68 def DaysInMonth(Month, Year):
69 """ Return the number of days in the specified month of a given year """
70 if Month in [1, 3, 5, 7, 8, 10, 12]:
73 elif Month in [4, 6, 9, 11]:
77 return 28+IsLeapYear(_setYear(Year))
80 raise opdate_error, "bad month `%s'" % str(Month)
83 def ValidDate(Day, Month, Year):
84 """ Verify that day, month, year is a valid date """
87 if (Day < 1) or (Year < MinYear) or (Year > MaxYear):
89 elif (Month >= 1) and (Month <= 12):
90 return Day <= DaysInMonth(Month, Year)
95 def DMYtoDate(Day, Month, Year):
96 """ Convert from day, month, year to a julian date """
99 if not ValidDate(Day, Month, Year):
102 if (Year == MinYear) and (Month < 3):
113 Year = Year - MinYear
115 return (((Year / 100)*146097) / 4) + (((Year % 100)*1461) / 4) + (((153*Month)+2) / 5)+Day+First2Months
118 def DateToDMY(Julian):
119 """ Convert from a julian date to day, month, year """
120 if Julian == BadDate:
123 if Julian <= First2Months:
132 I = (4*(Julian-First2Months))-1
133 J = (4*((I % 146097) / 4))+3
134 Year = (100*(I / 146097))+(J / 1461)
135 I = (5*(((J % 1461)+4) / 4))-3
137 Day = ((I % 153)+5) / 5
143 Year = Year + MinYear
145 return Day, Month, Year
148 def IncDate(Julian, Days, Months, Years):
149 """ Add (or subtract) the number of months, days, and years to a date.
150 Months and years are added before days. No overflow/underflow checks are made
152 Day, Month, Year = DateToDMY(Julian)
160 Year = Year + Months / 12
161 Month = Month + Months % 12
169 Julian = DMYtoDate(Day, Month, Year)
170 if Julian <> BadDate:
171 Julian = Julian + Days + Day28Delta
176 def IncDateTrunc(Julian, Months, Years):
177 """ Add (or subtract) the specified number of months and years to a date """
178 Day, Month, Year = DateToDMY(Julian)
186 Year = Year + Months / 12
187 Month = Month + Months % 12
195 Julian = DMYtoDate(Day, Month, Year)
196 if Julian <> BadDate:
197 MaxDay = DaysInMonth(Month, Year)
198 if Day+Day28Delta > MaxDay:
199 Julian = Julian + MaxDay-Day
201 Julian = Julian + Day28Delta
206 def DateDiff(Date1, Date2):
207 """ Return the difference in days,months,years between two valid julian dates """
208 #we want Date2 > Date1
214 #convert dates to day,month,year
215 Day1, Month1, Year1 = DateToDMY(Date1)
216 Day2, Month2, Year2 = DateToDMY(Date2)
224 Day2 = Day2 + DaysInMonth(Month2, Year2)
225 Days = abs(Day2-Day1)
227 #now months and years
231 Months = Month2-Month1
234 return Days, Months, Years
237 def DayOfWeek(Julian):
238 """ Return the day of the week for the date. Returns DayType(7) if Julian == BadDate. """
239 if Julian == BadDate:
240 raise opdate_error, "bad date `%s'" % str(Julian)
242 return (Julian+FirstDayOfWeek) % 7
245 def DayOfWeekDMY(Day, Month, Year):
246 """ Return the day of the week for the day, month, year """
247 return DayOfWeek( DMYtoDate(Day, Month, Year) )
250 #def MonthStringToMonth(MSt):
251 # """ Convert the month name in MSt to a month (1..12) or -1 on error """
252 # lmn = strptime.LongMonthNames[strptime.LANGUAGE]
253 # smn = strptime.ShortMonthNames[strptime.LANGUAGE]
254 # lmna = LongMonthNamesA
256 # I = FindStr(MSt, lmn)+1 or FindStr(MSt, smn)+1 or \
257 # FindStrUC(MSt, lmn)+1 or FindStrUC(MSt, smn)+1 or \
258 # FindStr(MSt, lmna)+1 or FindStrUC(MSt, lmna)+1
264 """ Returns today's date as a julian """
265 Year, Month, Day = localtime(time())[0:3]
266 return DMYtoDate(Day, Month, Year)
269 ### Time manipulation routines
273 """ Convert a Time variable to Hours, Minutes, Seconds """
278 Hours = T / SecondsInHour
279 T = T - Hours*SecondsInHour
280 Minutes = T / SecondsInMinute
281 T = T - Minutes*SecondsInMinute
284 return Hours, Minutes, Seconds
287 def HMStoTime(Hours, Minutes, Seconds):
288 """ Convert Hours, Minutes, Seconds to a Time variable """
289 Hours = Hours % HoursInDay
290 T = Hours*SecondsInHour + Minutes*SecondsInMinute + Seconds
292 return T % SecondsInDay
295 def ValidTime(Hours, Minutes, Seconds):
296 """ Return true if Hours:Minutes:Seconds is a valid time """
297 return (0 <= Hours < 24) and (0 <= Minutes < 60) and (0 <= Seconds < 60)
301 """ Returns current time in seconds since midnight """
302 Hours, Minutes, Seconds = localtime(time())[3:6]
303 return HMStoTime(Hours, Minutes, Seconds)
306 def TimeDiff(Time1, Time2):
307 """ Return the difference in hours,minutes,seconds between two times """
313 Hours, Minutes, Seconds = TimeToHMS(T)
314 return Hours, Minutes, Seconds
317 def IncTime(T, Hours, Minutes, Seconds):
318 """ Add the specified hours,minutes,seconds to T and return the result """
319 T = T + HMStoTime(Hours, Minutes, Seconds)
320 return T % SecondsInDay
323 def DecTime(T, Hours, Minutes, Seconds):
324 """ Subtract the specified hours,minutes,seconds from T and return the result """
325 Hours = Hours % HoursInDay
326 T = T - HMStoTime(Hours, Minutes, Seconds)
328 return T+SecondsInDay
333 def RoundToNearestHour(T, Truncate = False):
334 """ Round T to the nearest hour, or Truncate minutes and seconds from T """
335 Hours, Minutes, Seconds = TimeToHMS(T)
339 if Minutes >= (MinutesInHour / 2):
343 return HMStoTime(Hours, Minutes, Seconds)
346 def RoundToNearestMinute(T, Truncate = False):
347 """ Round T to the nearest minute, or Truncate seconds from T """
348 Hours, Minutes, Seconds = TimeToHMS(T)
351 if Seconds >= (SecondsInMinute / 2):
352 Minutes = Minutes + 1
355 return HMStoTime(Hours, Minutes, Seconds)
358 def DateTimeDiff(DT1, DT2):
359 """ Return the difference in days,seconds between two points in time """
360 # swap if DT1 later than DT2
361 if (DT1[0] > DT2[0]) or ((DT1[0] == DT2[0]) and (DT1[1] > DT2[1])):
366 # the difference in days is easy
369 # difference in seconds
371 # subtract one day, add 24 hours
373 DT2[1] = DT2[1] + SecondsInDay
379 def IncDateTime(DT1, Days, Secs):
380 """ Increment (or decrement) DT1 by the specified number of days and seconds
381 and put the result in DT2 """
385 DT2[0] = DT2[0] + Days
392 DT2[0] = DT2[0] - Secs / SecondsInDay
393 Secs = Secs % SecondsInDay
396 # subtract a day from DT2[0] and add a day's worth of seconds to DT2[1]
398 DT2[1] = DT2[1] + SecondsInDay
400 # now subtract the seconds
401 DT2[1] = DT2[1] - Secs
404 # increment the seconds
405 DT2[1] = DT2[1] + Secs
407 # adjust date if necessary
408 DT2[0] = DT2[0] + DT2[1] / SecondsInDay
410 # force time to 0..SecondsInDay-1 range
411 DT2[1] = DT2[1] % SecondsInDay
420 UTC_0Date = DMYtoDate(1, 1, 1970)
423 def DateTimeToGMT(Date, Time = False):
424 Date = Date - UTC_0Date
425 return Date*SecondsInDay + Time
428 def GMTtoDateTime(GMT):
429 q, r = divmod(GMT, SecondsInDay)
430 return q + UTC_0Date, r
437 LongMonthNamesA = ['Января', 'Февраля', 'Марта', 'Апреля', 'Мая', 'Июня',
438 'Июля', 'Августа', 'Сентября', 'Октября', 'Ноября', 'Декабря']
446 print "Is 1984 leap year?", IsLeapYear(1984)
447 print "Is 1990 leap year?", IsLeapYear(1990)
449 print "Days in month 8 year 1996:", DaysInMonth(8, 1996)
451 print "Is date 8/12/1996 valid?", ValidDate(8, 12, 1996)
452 print "Is date 40/11/1996 valid?", ValidDate(40, 11, 1996)
453 print "Is date 8/14/1996 valid?", ValidDate(8, 14, 1996)
455 print "Date->DMY for 138219:", DateToDMY(138219)
457 diff = DateDiff(DMYtoDate(12, 10, 1996), DMYtoDate(12, 10, 1997))
458 print "Date 12/10/1996 and date 12/10/1997 diff: %d years, %d months, %d days" % (diff[2], diff[1], diff[0])
460 diff = DateDiff(DMYtoDate(12, 10, 1996), DMYtoDate(12, 11, 1997))
461 print "Date 12/10/1996 and date 12/11/1997 diff: %d years, %d months, %d days" % (diff[2], diff[1], diff[0])
463 diff = DateDiff(DMYtoDate(31, 1, 1996), DMYtoDate(1, 3, 1996))
464 print "Date 31/01/1996 and date 01/03/1996 diff: %d years, %d months, %d days" % (diff[2], diff[1], diff[0])
467 #print "November is %dth month" % MonthStringToMonth("November")
469 print "Today is", Today()
470 print "Now is", CurrentTime()
472 print "My birthday 21 Dec 1967 is (must be Thursday):", day_name[DayOfWeekDMY(21, 12, 67)]
474 gmt = DateTimeToGMT(DMYtoDate(21, 12, 1967), HMStoTime(23, 45, 0))
475 print "21 Dec 1967, 23:45:00 --", gmtime(gmt) # DOS version of gmtime has error processing dates before 1/1/1970 :(
476 D, T = GMTtoDateTime(gmt)
477 print "(gmt) --", DateToDMY(D), TimeToHMS(T)
479 if __name__ == "__main__":