source: TI03-DataExtractor/trunk/pydxs/DateTimeManager.py @ 794

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI03-DataExtractor/trunk/pydxs/DateTimeManager.py@794
Revision 794, 11.0 KB checked in by astephen, 13 years ago (diff)

Unstable but latest version with multi-variable support and split hooks
for CDML and CSML.

RevLine 
[794]1#!/usr/bin/env python
2
3#   Copyright (C) 2004 CCLRC & NERC( Natural Environment Research Council ).
4#   This software may be distributed under the terms of the
5#   Q Public License, version 1.0 or later. http://ndg.nerc.ac.uk/public_docs/QPublic_license.txt
6
7helpMessage="""
8
9DateTimeManager.py
10==================
11
12Holds the class DateTimeManager that is a component time object copied
13from Bob Drach's cdtime within CDAT (Thanks Bob!). The reason for
14this duplication is that cdtime has dependencies on other software
15and is partly written in C. This version is entirely python and is
16therefore more portable.
17
18The class DateTimeManager has the following methods exposed to the user:
19
20    add(n, units) -  to add an interval to the current time object.
21    sub(n, units) - to subtract an interval to the current time object.
22    createList(s, e, i) - generate a list of times from s(tart) to e(nd)
23                        with i(nterval).
24    printtime(format_string)     - prints the time using typical python time formatting.
25    getDaysInMonth(month, year) - returns the number of days in a given month.
26
27The createList(s, e, i) function is a wrapper around DateTimeManager.createList() at the
28module level.
29
30
31Usage:
32======
33
34To create a date-time instance for midday Christmas day 2003:
35
36mytime=DateTimeManager(2003, 12, 25, 12, 0, 0)
37
38To add 3 months to the instance:
39
40mytime.add(3, "months")
41
42To create a list of dates and times:
43
44mylist=createList("1999-01-01 00:00:00", "1999-01-22 12:00:00", (6, "hour"))
45
46
47"""
48
49# Import standard library modules
50import re, types, time
51
52def daysInMonth(month, year):
53    """
54    Function wrapper around DateTimeManager.getDaysInMonth() method.
55    """
56    dt=DateTimeManager()
57    return dt.getDaysInMonth(month, year) 
58
59
60def createList(start, end, interval=(6, "hour"), listtype="string", formatstring="%Y-%m-%d %H:%M:%S"):
61    """
62    Function wrappper around DateTimeManager.createList() method.
63    """
64    dt=DateTimeManager()
65    return dt.createList(start, end, interval, listtype, formatstring)
66   
67   
68def getTimeBins(timelist):
69    """
70    Function wrapper around DateTimeManager.getTimeBins() method.
71    """
72    dt=DateTimeManager()
73    return dt.getTimeBins(timelist)
74
75
76
77class DateTimeManager:
78    """
79    Class to return lists of dates and times and allow adding and
80    subtracting of time intervals from time objects.
81    """
82   
83    # Class level parameters (do not change)
84    units={"year":"y ys yr yrs year years",
85           "month":"mon mons mnth mnths month months",
86           "day":"d ds dy dys day days",
87           "hour":"h hs hr hrs hour hours",
88           "minute":"min mins minute minutes",
89           "second":"s sc scs sec secs scnd scnds second seconds"}
90    positions=["year", "month", "day", "hour", "minute", "second"]
91    max=[99999, 13, None, 24, 60, 60] # These are the secs in mins etc...
92    min=[0, 1, 1, 0, 0, 0] 
93
94
95    def __init__(self, year=0, month=1, day=1, hour=0, minute=0, second=0):
96        """
97        Method to set up the instance formats and basic objects.
98        """
99        self.formats={"%Y":("%.4d","year"), "%y":("%.2d", "2dyear"), "%m":("%.2d","month"), "%d":("%.2d", "day"),
100             "%H":("%.2d", "hour"), "%M":("%.2d", "minute"), "%S":("%.2d", "second")}       
101        self.datetime=[year, month, day, hour, minute, second]
102        for i in range(0,6):
103            if type(self.datetime[i])!=types.IntType:
104                raise "Time components should be an integer: %s" % self.datetime[i]
105            max=DateTimeManager.max
106            max[2]=self.getDaysInMonth(month, year)
107            if self.datetime[i]>=max[i]:
108                raise "Time component '%s' must be less than limits: %s" % (self.datetime[i], str(max))
109        #print self.__repr__()
110
111
112    ##########################################
113    #
114    # __getattr__() method
115    #
116    ##########################################
117    def __getattr__(self, att):
118        if att in DateTimeManager.positions:
119            return self.datetime[DateTimeManager.positions.index(att)]
120        elif att=="datetime":
121            return self.__repr__()
122        return "Attribute not found: %s" % att
123
124
125    ##########################################
126    #
127    # __repr__() method
128    #
129    ##########################################
130    def __repr__(self):
131        return "%.4d-%.2d-%.2d %.2d:%.2d:%.2d" % tuple(self.datetime)
132       
133 
134    ##########################################
135    #
136    # __str__() method
137    #
138    ##########################################
139    def __str__(self):
140        return "%.4d-%.2d-%.2d %.2d:%.2d:%.2d" % tuple(self.datetime)
141
142
143    ##########################################
144    #
145    # add() method
146    #
147    ##########################################
148    def add(self, n, unit="hour"):
149        self.datetime=self._add(n, unit, self.datetime)
150        return self.__repr__()
151
152
153    ##########################################
154    #
155    # _add() method
156    #
157    ##########################################
158    def _add(self, n, unit="hour", itime=None):
159        unit=unit.lower()
160        if type(n)==types.TupleType:
161            increment=n
162        else:
163            for i in DateTimeManager.units.keys():
164                if i.find(unit)>-1 or DateTimeManager.units[i].find(unit)>-1:
165                    unit=i
166                    unitindex=DateTimeManager.positions.index(unit)
167                    increment=[0,0,0,0,0,0]
168                    increment[unitindex]=n
169                    break
170            itime=self._recalculate(increment, itime)
171        return itime
172
173
174    ##########################################
175    #
176    # _recalculate() method
177    #
178    ##########################################
179    def _recalculate(self, increment, itime):
180        max=DateTimeManager.max
181        min=DateTimeManager.min
182        for x in range(5,-1,-1):
183            if increment[x]==0:
184                continue
185            else:
186                if x==2:  # Calc days in month
187                    max[x]=self.getDaysInMonth(itime[1], itime[0])+1                 
188                itime[x]=itime[x]+increment[x]
189                if itime[x]>=max[x]:
190                    remainder=itime[x]%max[x]
191                    up_one=itime[x]/max[x]
192                    if remainder==0:
193                      itime[x]=min[x]
194                    else:
195                      itime[x]=remainder
196                    itime[x]
197                    increment[x-1]=increment[x-1]+up_one
198        #print itime
199        return itime
200
201
202    ##########################################
203    #
204    # sub() method
205    #
206    ##########################################
207    def sub(self, n, unit="hour"):
208        pass
209
210
211    ##########################################
212    #
213    # createList() method
214    #
215    ##########################################
216    def createList(self, start, end, interval=(6, "hour"), listtype="string", formatstring="%Y-%m-%d %H:%M:%S"):
217        if type(start)==types.StringType:
218            timepatt=("(\d{4})-(\d{1,2})-(\d{1,2})[ T](\d{1,2}):(\d{1,2}):(\d{1,2})")
219            startmatch=re.match(timepatt, start)
220            endmatch=re.match(timepatt, end)
221            if startmatch:
222                start=[]
223                for i in startmatch.groups():
224                    start.append(int(i))
225            if endmatch:
226                end=[]
227                for i in list(endmatch.groups()):
228                    end.append(int(i))
229        else:
230            filler=[0,1,1,0,0,0]
231            start=list(start)+filler[len(start):]
232            end=list(end)+filler[len(end):]
233            if type(start[0])!=type(1):
234                startlist=[]
235                endlist=[]
236                for i in range(6):
237                    startlist.append(int(start[i]))
238                    endlist.append(int(end[i]))
239                start=startlist
240                end=endlist
241           
242        now=start
243        rtlist=[]
244        end[-1]=end[-1]+1   # add one second to end so it catches it in while loop
245        while now<end:
246            #print "%.4d-%.2d-%.2d %.2d:%.2d:%.2d" % tuple(now), "%.4d-%.2d-%.2d %.2d:%.2d:%.2d" % tuple(end)
247            if listtype=="string":
248                rtlist.append(self.formatTime(formatstring, tuple(now)))
249            else:
250                rtlist.append(tuple(now))
251            now=self._add(interval[0], interval[1], now)
252        return rtlist
253   
254
255    ##########################################
256    #
257    # getDaysInMonth() method
258    #
259    ##########################################
260    def getDaysInMonth(self, month, year):
261        if month==2 and year%4==0:
262            return 29
263        else:
264            monthmap=(None, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
265            return monthmap[month]
266           
267           
268    ##########################################
269    #
270    # printtime() method
271    #
272    ##########################################
273    def printtime(self, formatstring="%Y-%m-%d %H:%M:%S", itime=None):
274        ftime=self.formatTime(formatstring, itime)
275        print ftime
276        return
277           
278           
279    ##########################################
280    #
281    # formatTime() method
282    #
283    ##########################################
284    def formatTime(self, formatstring="%Y-%m-%d %H:%M:%S", itime=None):
285        if itime==None: itime=self.datetime
286        #itimeDict={}
287        #count=0
288        #for k in ("year", "month", "day", "hour", "minute", "second"):   
289        #    itimeDict[k]=itime[count]
290        #    count=count+1         
291        #checkCount=0
292        formatstring=time.strftime(formatstring, tuple(list((itime))+[0,1,0]))
293        #while formatstring.find("%")>-1:  # Keep in while loop just in case more than one occurrence of a field required
294        #    checkCount=checkCount+1
295        #    for f in self.formats.keys():
296        #        (formatter, item)=self.formats[f]
297        #       if type(item)==types.StringType:
298        #            replacer=formatter % itimeDict[item]
299        #       else:
300        #           replacer=formatter % (apply(item, (itime,)))
301        #       formatstring=formatstring.replace(f, replacer)
302        #    if checkCount>10: 
303        #       raise "Cannot interpret remaining characters in: '%s'" % (formatstring)         
304        return formatstring
305       
306    def getTimeBins(self, timelist):
307        """
308        Method to collect all available values of year, month, day etc into individual
309        lists for populating selection boxes.
310        """
311        # check type of input list
312        if type(timelist[0])!=tuple:
313            raise "Timelist items must be tuples."
314        # Create an empty list
315        nitems=len(timelist[0])
316        binlist=[]
317        for i in range(nitems):
318            binlist.append([])
319           
320        # Populate the return list   
321        for t in timelist:
322            for i in range(nitems):
323                if t[i] not in binlist[i]: binlist[i].append(t[i])
324               
325        # Make sure they are sorted
326        for i in range(nitems):
327            binlist[i].sort()
328           
329        return binlist
330       
331
332##############################################
333#
334# class UMTime
335#
336##############################################
337class UMTime(DateTimeManager):
338
339    ##########################################
340    #
341    # __init__() method
342    #
343    ##########################################
344    def __init__(self, year=0, month=1, day=1, hour=0, minute=0, second=0):
345        DateTimeManager.__init__(self, year, month, day, hour, minute, second)
346        self.formats["%umyear"]=("%.4d_%s", self.getUMYear)   
347
348
349    ##########################################
350    #
351    # getUMYear() method
352    #
353    ##########################################
354    def getUMYear(self, itime):
355        umyear=itime[0]+1800
356        return (umyear, "holiday") 
357 
358       
359       
360                   
361                   
362
363
364   
Note: See TracBrowser for help on using the repository browser.