-
Notifications
You must be signed in to change notification settings - Fork 1
/
dateutils.py
executable file
·144 lines (122 loc) · 4.53 KB
/
dateutils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
from __future__ import print_function
import datetime, calendar
"""
utilities for working with dates using datetime module (Python 2.3 or later)
Jeff Whitaker <[email protected]>
"""
hrsgregstart = 13865688 # hrs from 00010101 to 15821015 in Julian calendar.
# times in many datasets use mixed Gregorian/Julian calendar, datetime
# module uses a proleptic Gregorian calendar. So, I use datetime to compute
# hours since start of Greg. calendar (15821015) and add this constant to
# get hours since 1-Jan-0001 in the mixed Gregorian/Julian calendar.
gregstart = datetime.datetime(1582,10,15) # datetime.datetime instance
day1 = datetime.datetime(1,1,1) # datetime.datetime instance
def dateto_hrs_since_day1CE(curdate,mixedcal=True):
"""given datetime.datetime instance, compute hours since 1-Jan-0001"""
if mixedcal:
if curdate < gregstart:
msg = 'date must be after start of gregorian calendar (15821015)!'
raise ValueErrorr(msg)
difftime = curdate-gregstart
hrsdiff = 24*difftime.days + difftime.seconds/3600
return hrsdiff+hrsgregstart
else:
difftime = curdate-day1
return 24.*(difftime.days+1)+difftime.seconds/3600.
def hrs_since_day1CE_todate(hrs,mixedcal=True):
"""return datetime.datetime instance given hours since 1-Jan-0001"""
if hrs < 0.0:
msg = "hrs must be positive!"
raise ValueError(msg)
delta = datetime.timedelta(hours=1)
if mixedcal:
hrs_sincegreg = hrs - hrsgregstart
curdate = gregstart + hrs_sincegreg*delta
else:
curdate = hrs*delta
return curdate
def dateshift(analdate,fcsthr):
"""
verifdate = incdate(analdate, fcsthr)
compute verification date given analysis date string (yyyymmddhh) and
fcst hour.
"""
yyyy,mm,dd,hh = splitdate(analdate)
analdate = datetime.datetime(yyyy,mm,dd,hh)
verifdate = analdate + fcsthr*datetime.timedelta(hours=1)
verifdate = makedate(verifdate.year,verifdate.month,verifdate.day,verifdate.hour)
return verifdate
def splitdate(yyyymmddhh):
"""
yyyy,mm,dd,hh = splitdate(yyyymmddhh)
give an date string (yyyymmddhh) return integers yyyy,mm,dd,hh.
"""
yyyy = int(yyyymmddhh[0:4])
mm = int(yyyymmddhh[4:6])
dd = int(yyyymmddhh[6:8])
hh = int(yyyymmddhh[8:10])
return yyyy,mm,dd,hh
def makedate(yyyy,mm,dd,hh):
"""
yyyymmddhh = makedate(yyyy,mm,dd,hh)
return a date string of the form yyyymmddhh given integers yyyy,mm,dd,hh.
"""
return '%0.4i'%(yyyy)+'%0.2i'%(mm)+'%0.2i'%(dd)+'%0.2i'%(hh)
def hrstodate(hrs,mixedcal=True):
"""
yyyymmddhh = hrstodate(hrs)
return a date string of the form yyyymmddhh given hrs since day 1 CE.
"""
date = hrs_since_day1CE_todate(hrs,mixedcal=mixedcal)
return makedate(date.year,date.month,date.day,date.hour)
def datetohrs(yyyymmddhh,mixedcal=True):
"""
hrs = hrstodate(yyyymmddhh)
return hrs since day 1 CE given a date string of the form yyyymmddhh.
"""
yyyy,mm,dd,hh = splitdate(yyyymmddhh)
return dateto_hrs_since_day1CE(datetime.datetime(yyyy,mm,dd,hh),mixedcal=mixedcal)
def daterange(date1,date2,hrinc):
"""
date_list = daterange(date1,date2,hrinc)
return of list of date strings of the form yyyymmddhh given
a starting date, ending date and an increment in hours.
"""
date = date1
delta = datetime.timedelta(hours=1)
yyyy,mm,dd,hh = splitdate(date)
d = datetime.datetime(yyyy,mm,dd,hh)
n = 0
dates = [date]
while date < date2:
d = d + hrinc*delta
date = makedate(d.year,d.month,d.day,d.hour)
dates.append(date)
n = n + 1
return dates
def dayofyear(yyyy,mm,dd):
"""
return integer day of year given yyyy,mm,dd
"""
d = datetime.datetime(yyyy,mm,dd)
d0 = datetime.datetime(yyyy,1,1)
return (d-d0).days
def getyrmon(day_of_year,yyyy=2001):
d1 = datetime.datetime(yyyy,1,1)
if calendar.isleap(d1.year) and day_of_year > 366:
raise ValueError('not that many days in the year')
if not calendar.isleap(d1.year) and day_of_year > 365:
raise ValueError('not that many days in the year')
d2 = d1 + (day_of_year-1)*datetime.timedelta(days=1)
return d2.month,d2.day
def daysinmonth(yyyy,mm):
"""
return number of days in month given yyyy,mm
"""
return calendar.monthrange(yyyy,mm)[1]
if __name__ == "__main__":
print(dayofyear(2000,2,29))
print(daysinmonth(2000,2))
print(datetohrs('0001010100',mixedcal=False))
print(datetohrs('2001010100',mixedcal=False))
print(datetohrs('2001010100',mixedcal=True))