2 # -*- coding: koi8-r -*-
5 # opDate - date/time manipulation routines
6 # Some ideas came from Turbo Professional/Object Professional (t/o)pDate.PAS
12 from calendar import *
13 from opstring import *
18 MinDate = 0x00000000 # = 01/01/1600
19 MaxDate = 0x000D6025 # = 12/31/3999
20 Date1900 = 0x0001AC05 # = 01/01/1900
21 Date1980 = 0x00021E28 # = 01/01/1980
22 Date2000 = 0x00023AB1 # = 01/01/2000
27 MinTime = 0 # = 00:00:00 am
28 MaxTime = 86399 # = 23:59:59 pm
31 SecondsInDay = 86400 # number of seconds in a day
32 SecondsInHour = 3600 # number of seconds in an hour
33 SecondsInMinute = 60 # number of seconds in a minute
34 HoursInDay = 24 # number of hours in a day
35 MinutesInHour = 60 # number of minutes in an hour
37 First2Months = 59 # 1600 was a leap year
38 FirstDayOfWeek = 5 # 01/01/1600 was a Saturday
42 class opdate_error(Exception):
47 ### Date manipulation routines
51 if ( (Year % 4 == 0) and (Year % 4000 <> 0) and ((Year % 100 <> 0) or (Year % 400 == 0)) ):
60 if Year < Threshold2000:
65 def DaysInMonth(Month, Year):
66 """ Return the number of days in the specified month of a given year """
67 if Month in [1, 3, 5, 7, 8, 10, 12]:
70 elif Month in [4, 6, 9, 11]:
74 return 28+IsLeapYear(_setYear(Year))
77 raise opdate_error, "bad month `%s'" % str(Month)
80 def ValidDate(Day, Month, Year):
81 """ Verify that day, month, year is a valid date """
84 if (Day < 1) or (Year < MinYear) or (Year > MaxYear):
86 elif (Month >= 1) and (Month <= 12):
87 return Day <= DaysInMonth(Month, Year)
92 def DMYtoDate(Day, Month, Year):
93 """ Convert from day, month, year to a julian date """
96 if not ValidDate(Day, Month, Year):
99 if (Year == MinYear) and (Month < 3):
110 Year = Year - MinYear
112 return (((Year / 100)*146097) / 4) + (((Year % 100)*1461) / 4) + (((153*Month)+2) / 5)+Day+First2Months
115 def DateToDMY(Julian):
116 """ Convert from a julian date to day, month, year """
117 if Julian == BadDate:
120 if Julian <= First2Months:
129 I = (4*(Julian-First2Months))-1
130 J = (4*((I % 146097) / 4))+3
131 Year = (100*(I / 146097))+(J / 1461)
132 I = (5*(((J % 1461)+4) / 4))-3
134 Day = ((I % 153)+5) / 5
140 Year = Year + MinYear
142 return Day, Month, Year
145 def IncDate(Julian, Days, Months, Years):
146 """ Add (or subtract) the number of months, days, and years to a date.
147 Months and years are added before days. No overflow/underflow checks are made
149 Day, Month, Year = DateToDMY(Julian)
157 Year = Year + Months / 12
158 Month = Month + Months % 12
166 Julian = DMYtoDate(Day, Month, Year)
167 if Julian <> BadDate:
168 Julian = Julian + Days + Day28Delta
173 def IncDateTrunc(Julian, Months, Years):
174 """ Add (or subtract) the specified number of months and years to a date """
175 Day, Month, Year = DateToDMY(Julian)
183 Year = Year + Months / 12
184 Month = Month + Months % 12
192 Julian = DMYtoDate(Day, Month, Year)
193 if Julian <> BadDate:
194 MaxDay = DaysInMonth(Month, Year)
195 if Day+Day28Delta > MaxDay:
196 Julian = Julian + MaxDay-Day
198 Julian = Julian + Day28Delta
203 def DateDiff(Date1, Date2):
204 """ Return the difference in days,months,years between two valid julian dates """
205 #we want Date2 > Date1
211 #convert dates to day,month,year
212 Day1, Month1, Year1 = DateToDMY(Date1)
213 Day2, Month2, Year2 = DateToDMY(Date2)
221 Day2 = Day2 + DaysInMonth(Month2, Year2)
222 Days = abs(Day2-Day1)
224 #now months and years
228 Months = Month2-Month1
231 return Days, Months, Years
234 def DayOfWeek(Julian):
235 """ Return the day of the week for the date. Returns DayType(7) if Julian == BadDate. """
236 if Julian == BadDate:
237 raise opdate_error, "bad date `%s'" % str(Julian)
239 return (Julian+FirstDayOfWeek) % 7
242 def DayOfWeekDMY(Day, Month, Year):
243 """ Return the day of the week for the day, month, year """
244 return DayOfWeek( DMYtoDate(Day, Month, Year) )
247 #def MonthStringToMonth(MSt):
248 # """ Convert the month name in MSt to a month (1..12) or -1 on error """
249 # lmn = strptime.LongMonthNames[strptime.LANGUAGE]
250 # smn = strptime.ShortMonthNames[strptime.LANGUAGE]
251 # lmna = LongMonthNamesA
253 # I = FindStr(MSt, lmn)+1 or FindStr(MSt, smn)+1 or \
254 # FindStrUC(MSt, lmn)+1 or FindStrUC(MSt, smn)+1 or \
255 # FindStr(MSt, lmna)+1 or FindStrUC(MSt, lmna)+1
261 """ Returns today's date as a julian """
262 Year, Month, Day = localtime(time())[0:3]
263 return DMYtoDate(Day, Month, Year)
266 ### Time manipulation routines
270 """ Convert a Time variable to Hours, Minutes, Seconds """
275 Hours = T / SecondsInHour
276 T = T - Hours*SecondsInHour
277 Minutes = T / SecondsInMinute
278 T = T - Minutes*SecondsInMinute
281 return Hours, Minutes, Seconds
284 def HMStoTime(Hours, Minutes, Seconds):
285 """ Convert Hours, Minutes, Seconds to a Time variable """
286 Hours = Hours % HoursInDay
287 T = Hours*SecondsInHour + Minutes*SecondsInMinute + Seconds
289 return T % SecondsInDay
292 def ValidTime(Hours, Minutes, Seconds):
293 """ Return true if Hours:Minutes:Seconds is a valid time """
294 return (0 <= Hours < 24) and (0 <= Minutes < 60) and (0 <= Seconds < 60)
298 """ Returns current time in seconds since midnight """
299 Hours, Minutes, Seconds = localtime(time())[3:6]
300 return HMStoTime(Hours, Minutes, Seconds)
303 def TimeDiff(Time1, Time2):
304 """ Return the difference in hours,minutes,seconds between two times """
310 Hours, Minutes, Seconds = TimeToHMS(T)
311 return Hours, Minutes, Seconds
314 def IncTime(T, Hours, Minutes, Seconds):
315 """ Add the specified hours,minutes,seconds to T and return the result """
316 T = T + HMStoTime(Hours, Minutes, Seconds)
317 return T % SecondsInDay
320 def DecTime(T, Hours, Minutes, Seconds):
321 """ Subtract the specified hours,minutes,seconds from T and return the result """
322 Hours = Hours % HoursInDay
323 T = T - HMStoTime(Hours, Minutes, Seconds)
325 return T+SecondsInDay
330 def RoundToNearestHour(T, Truncate = False):
331 """ Round T to the nearest hour, or Truncate minutes and seconds from T """
332 Hours, Minutes, Seconds = TimeToHMS(T)
336 if Minutes >= (MinutesInHour / 2):
340 return HMStoTime(Hours, Minutes, Seconds)
343 def RoundToNearestMinute(T, Truncate = False):
344 """ Round T to the nearest minute, or Truncate seconds from T """
345 Hours, Minutes, Seconds = TimeToHMS(T)
348 if Seconds >= (SecondsInMinute / 2):
349 Minutes = Minutes + 1
352 return HMStoTime(Hours, Minutes, Seconds)
355 def DateTimeDiff(DT1, DT2):
356 """ Return the difference in days,seconds between two points in time """
357 # swap if DT1 later than DT2
358 if (DT1[0] > DT2[0]) or ((DT1[0] == DT2[0]) and (DT1[1] > DT2[1])):
363 # the difference in days is easy
366 # difference in seconds
368 # subtract one day, add 24 hours
370 DT2[1] = DT2[1] + SecondsInDay
376 def IncDateTime(DT1, Days, Secs):
377 """ Increment (or decrement) DT1 by the specified number of days and seconds
378 and put the result in DT2 """
382 DT2[0] = DT2[0] + Days
389 DT2[0] = DT2[0] - Secs / SecondsInDay
390 Secs = Secs % SecondsInDay
393 # subtract a day from DT2[0] and add a day's worth of seconds to DT2[1]
395 DT2[1] = DT2[1] + SecondsInDay
397 # now subtract the seconds
398 DT2[1] = DT2[1] - Secs
401 # increment the seconds
402 DT2[1] = DT2[1] + Secs
404 # adjust date if necessary
405 DT2[0] = DT2[0] + DT2[1] / SecondsInDay
407 # force time to 0..SecondsInDay-1 range
408 DT2[1] = DT2[1] % SecondsInDay
417 UTC_0Date = DMYtoDate(1, 1, 1970)
420 def DateTimeToGMT(Date, Time = False):
421 Date = Date - UTC_0Date
422 return Date*SecondsInDay + Time
425 def GMTtoDateTime(GMT):
426 q, r = divmod(GMT, SecondsInDay)
427 return q + UTC_0Date, r
434 LongMonthNamesA = ['Января', 'Февраля', 'Марта', 'Апреля', 'Мая', 'Июня',
435 'Июля', 'Августа', 'Сентября', 'Октября', 'Ноября', 'Декабря']
443 print "Is 1984 leap year?", IsLeapYear(1984)
444 print "Is 1990 leap year?", IsLeapYear(1990)
446 print "Days in month 8 year 1996:", DaysInMonth(8, 1996)
448 print "Is date 8/12/1996 valid?", ValidDate(8, 12, 1996)
449 print "Is date 40/11/1996 valid?", ValidDate(40, 11, 1996)
450 print "Is date 8/14/1996 valid?", ValidDate(8, 14, 1996)
452 print "Date->DMY for 138219:", DateToDMY(138219)
454 diff = DateDiff(DMYtoDate(12, 10, 1996), DMYtoDate(12, 10, 1997))
455 print "Date 12/10/1996 and date 12/10/1997 diff: %d years, %d months, %d days" % (diff[2], diff[1], diff[0])
457 diff = DateDiff(DMYtoDate(12, 10, 1996), DMYtoDate(12, 11, 1997))
458 print "Date 12/10/1996 and date 12/11/1997 diff: %d years, %d months, %d days" % (diff[2], diff[1], diff[0])
460 diff = DateDiff(DMYtoDate(31, 1, 1996), DMYtoDate(1, 3, 1996))
461 print "Date 31/01/1996 and date 01/03/1996 diff: %d years, %d months, %d days" % (diff[2], diff[1], diff[0])
464 #print "November is %dth month" % MonthStringToMonth("November")
466 print "Today is", Today()
467 print "Now is", CurrentTime()
469 print "My birthday 21 Dec 1967 is (must be Thursday):", day_name[DayOfWeekDMY(21, 12, 67)]
471 gmt = DateTimeToGMT(DMYtoDate(21, 12, 1967), HMStoTime(23, 45, 0))
472 print "21 Dec 1967, 23:45:00 --", gmtime(gmt) # DOS version of gmtime has error processing dates before 1/1/1970 :(
473 D, T = GMTtoDateTime(gmt)
474 print "(gmt) --", DateToDMY(D), TimeToHMS(T)
476 if __name__ == "__main__":