Jack Jansen | 816cf9d | 2000-10-12 21:20:41 +0000 | [diff] [blame] | 1 | """ strptime version 1.3, Time-stamp: <96/09/23 21:22:24 flognat> |
| 2 | The reverse of strftime. |
| 3 | |
| 4 | Copyright (C) 1996 Andy Eskilsson, flognat@fukt.hk-r.se |
| 5 | |
| 6 | This is free software; unrestricted redistribution is allowed under the |
| 7 | terms of the GPL. For full details of the license conditions of this |
| 8 | software, see the GNU General Public License. |
| 9 | |
| 10 | And here comes the documentation: |
| 11 | |
| 12 | Throw a string and a format specification at strptime and if everything |
| 13 | is ok you will get a tuple containing 9 items that are compatible with |
| 14 | pythons time-module. |
| 15 | |
| 16 | interface: |
| 17 | strptime(inputstring, formatstring) |
| 18 | |
| 19 | Little errorchecking... so you'd better know what you are doing. |
| 20 | |
| 21 | example: |
| 22 | from strptime import * |
| 23 | mktime(strptime("26/6 1973", "%d/%m %Y")) |
| 24 | |
| 25 | And voila you have the second when the author of this function was born. |
| 26 | |
| 27 | The supported format identifiers are: |
| 28 | %a weekday in short text-form, e.g. Mon |
| 29 | %A weekday in long text-form, e.g. Monday |
| 30 | %b month in short text-form, e.g. Jul |
| 31 | %B month in long text-form e.g. July |
| 32 | %c the format specified by DateAndTimeRepresentation |
| 33 | %d the day in month in numeric form, e.g. 24 |
| 34 | %H hour in 24 hour form |
| 35 | %j julian day (day of year) |
| 36 | %m month in numeric format |
| 37 | %M minute |
| 38 | %S second |
| 39 | %T Time in '%H:%M:%S'-format |
| 40 | %w weekday, 0=monday |
| 41 | %x date in format represented by DateRepresentation |
| 42 | %X time in format represented by TimeRepresentation |
| 43 | %y year in short form |
| 44 | %Y year in long form |
| 45 | %% %-sign |
| 46 | |
| 47 | I have done some thinking here (*REALLY*) and it is possible to configure |
| 48 | this module so it uses other languages by adding their names to the |
| 49 | dictionaries first in the file, and setting the variable LANGUAGE. |
| 50 | |
| 51 | For your exercise I have inserted the swedish names ;-) |
| 52 | |
| 53 | The lfind, name, complex, numbers and parse functions are for internal |
| 54 | use, called by strptime. |
| 55 | |
| 56 | Uh.. oh yeah.. if you want to get in touch with me.. I am reachable |
| 57 | at flognat@fukt.hk-r.se, the newest version of this file can probably |
| 58 | be found somewhere close to http://www.fukt.hk-r.se/~flognat |
| 59 | |
| 60 | If you like it, send a postcard to Andy Eskilsson |
| 61 | Kämnärsv. 3b228 |
| 62 | S-226 46 Lund |
| 63 | Sweden |
| 64 | |
| 65 | Uhm be gentle with the bug-reports, its the first time for me ;-) |
| 66 | |
| 67 | """ |
| 68 | |
| 69 | import string |
| 70 | |
| 71 | LongDayNames={ 'English' : [ 'Monday', 'Tuesday', 'Wednesday', |
| 72 | 'Thursday', 'Friday', 'Saturday', 'Sunday'], |
| 73 | 'Swedish' : [ 'Måndag', 'Tisdag', 'Onsdag', 'Torsdag', |
| 74 | 'Fredag', 'Lördag', 'Söndag']} |
| 75 | ShortDayNames={ 'English' : [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], |
| 76 | 'Swedish' : [ 'Mån', 'Tis', 'Ons', 'Tor', 'Fre', 'Lör', 'Sön']} |
| 77 | |
| 78 | LongMonthNames={ 'English' : ['none', 'January', 'February', 'March', 'April', |
| 79 | 'May', 'June', 'July', 'August', 'September', |
| 80 | 'October', 'November', 'December'], |
| 81 | 'Swedish' : ['none', 'Januari', 'Februari', 'Mars', 'April', |
| 82 | 'Maj', 'Juni', 'Juli', 'Augusti','September', |
| 83 | 'Oktober', 'November', 'December'] } |
| 84 | ShortMonthNames={ 'English' : ['none', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', |
| 85 | 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], |
| 86 | 'Swedish' : ['none', 'Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', |
| 87 | 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec']} |
| 88 | DateAndTimeRepresentation={ 'English' : '%a %b %d %H:%m:%S %Y', |
| 89 | 'Swedish' : '%a %d %b %Y %H:%m:%S' } |
| 90 | |
| 91 | DateRepresentation = { 'English' : '%m/%d/%y', |
| 92 | 'Swedish' : '%d/%m/%y'} |
| 93 | |
| 94 | TimeRepresentation = { 'English' : '%H:%M:%S', |
| 95 | 'Swedish' : '%H:%M:%S'} |
| 96 | |
| 97 | LANGUAGE='English' |
| 98 | |
| 99 | BadFormatter='An illegal formatter was given' |
| 100 | |
| 101 | #Check if strinf begins with substr |
| 102 | def lfind(str, substr): |
| 103 | return string.lower(str[:len(substr)])==string.lower(substr) |
| 104 | |
| 105 | #atoms consisting of other atoms |
| 106 | def complex(str, format, base): |
| 107 | code=format[:1] |
| 108 | if code=='c': |
| 109 | string=DateAndTimeRepresentation[LANGUAGE] |
| 110 | elif code=='T': |
| 111 | string='%H:%M:%S' |
| 112 | elif code=='x': |
| 113 | string=DateRepresentation[LANGUAGE] |
| 114 | elif code=='X': |
| 115 | string=TimeRepresentation[LANGUAGE] |
| 116 | |
| 117 | return parse(str, string, base) |
| 118 | |
| 119 | #string based names |
| 120 | def names(str, format, base): |
| 121 | code=format[:1] |
| 122 | if code=='a': |
| 123 | selection=ShortDayNames[LANGUAGE] |
| 124 | result='weekd' |
| 125 | elif code=='A': |
| 126 | selection=LongDayNames[LANGUAGE] |
| 127 | result='weekd' |
| 128 | elif code=='b': |
| 129 | selection=ShortMonthNames[LANGUAGE] |
| 130 | result='month' |
| 131 | elif code=='B': |
| 132 | selection=LongMonthNames[LANGUAGE] |
| 133 | result='month' |
| 134 | |
| 135 | match=None |
| 136 | for i in selection: |
| 137 | if lfind(str, i): |
| 138 | match=i |
| 139 | break |
| 140 | |
| 141 | base[result]=selection.index(match) |
| 142 | return len(match) |
| 143 | |
| 144 | #numeric stuff |
| 145 | def numeric(str, format, base): |
| 146 | code=format[:1] |
| 147 | if code=='d': result='day' |
| 148 | elif code=='H': result='hour' |
| 149 | elif code=='j': result='juliand' |
| 150 | elif code=='m': result='month' |
| 151 | elif code=='M': result='min' |
| 152 | elif code=='S': result='sec' |
| 153 | elif code=='w': result='weekd' |
| 154 | elif code=='y': result='shortYear' |
| 155 | elif code=='Y': result='year' |
| 156 | |
| 157 | i=0 |
| 158 | while str[i] in string.whitespace: i=i+1 |
| 159 | j=i |
| 160 | if len(format)>1: |
| 161 | while not str[j] in string.whitespace and str[j]!=format[1]: j=j+1 |
| 162 | else: |
| 163 | try: |
| 164 | while not str[j] in string.whitespace: j=j+1 |
| 165 | except IndexError: |
| 166 | pass |
| 167 | |
| 168 | # hmm could check exception here, but what could I add? |
| 169 | base[result]=string.atoi(str[i:j]) |
| 170 | |
| 171 | return j |
| 172 | |
| 173 | parseFuns={ 'a':names, 'A':names, 'b':names, 'B':names, 'c':complex, 'd':numeric, |
| 174 | 'H':numeric, 'j':numeric, 'm':numeric, 'M':numeric, 'S':numeric, |
| 175 | 'T':complex, 'w':numeric, 'x':complex, 'y':numeric, 'Y':numeric} |
| 176 | |
| 177 | # Well split up in atoms, reason to why this is separated from atrptime |
| 178 | # is to be able to reparse complex atoms |
| 179 | def parse(str, format, base): |
| 180 | atoms=string.split(format, '%') |
| 181 | charCounter=0 |
| 182 | atomCounter=0 |
| 183 | |
| 184 | # Hey I am laazy and think that the format is exactly what the string is! |
| 185 | charCounter=charCounter+len(atoms[atomCounter]) |
| 186 | atomCounter=atomCounter+1 |
| 187 | |
| 188 | while atomCounter < len(atoms) and charCounter < len(str): |
| 189 | atom=atoms[atomCounter] |
| 190 | |
| 191 | if atom=='': # escaped |
| 192 | charCounter=charCounter+1 |
| 193 | atomCounter=atomCounter+1 |
| 194 | charCounter=charCounter+len(atoms[atomCounter]) |
| 195 | else: |
| 196 | try: |
| 197 | parsefunction=parseFuns[atom[:1]] |
| 198 | except KeyError: |
| 199 | raise BadFormatter, atom[:1] |
| 200 | grabbed=apply(parsefunction, (str[charCounter:], atom, base)) |
| 201 | charCounter=charCounter+grabbed+len(atom)-1 |
| 202 | |
| 203 | atomCounter=atomCounter+1 |
| 204 | |
| 205 | return charCounter |
| 206 | |
| 207 | # Ok here we go, tadaaa --> STRPTIME <-- at last.. |
| 208 | def strptime(str, format): |
| 209 | """Converts str specified by format to tuple useable by the time module""" |
| 210 | returnTime={} |
| 211 | returnTime['year']=0 |
| 212 | returnTime['shortYear']=None |
| 213 | returnTime['month']=0 |
| 214 | returnTime['day']=0 |
| 215 | returnTime['hour']=0 |
| 216 | returnTime['min']=0 |
| 217 | returnTime['sec']=0 |
| 218 | returnTime['weekd']=0 |
| 219 | returnTime['juliand']=0 |
| 220 | returnTime['dst']=0 |
| 221 | |
| 222 | parse(str, format, returnTime) |
| 223 | |
| 224 | if returnTime['shortYear']!=None: |
| 225 | returnTime['year']=returnTime['shortYear']+1900 |
| 226 | |
| 227 | return (returnTime['year'], returnTime['month'], returnTime['day'], |
| 228 | returnTime['hour'], returnTime['min'], returnTime['sec'], |
| 229 | returnTime['weekd'], returnTime['juliand'], returnTime['dst']) |
| 230 | |
| 231 | # just for my convenience |
| 232 | def strpdebug(): |
| 233 | import pdb |
| 234 | pdb.run('strptime("% Tue 3 Feb", "%% %a %d %b")') |
| 235 | |
| 236 | def test(): |
| 237 | from time import * |
| 238 | a=asctime(localtime(time())) |
| 239 | print a |
| 240 | b=strptime(a, '%a %b %d %H:%M:%S %Y') |
| 241 | print asctime(b) |
| 242 | print strptime("%% % Tue 3 Feb", "%%%% %% %a %d %b") |
| 243 | print strptime('Thu, 12 Sep 1996 19:42:06 GMT', '%a, %d %b %Y %T GMT') |
| 244 | print strptime('Thu, 12 Sep 1996 19:42:06 GMT', '%a, %d %b %Y %T') |
| 245 | print strptime('Thu, 12 Sep 1996 19:42:06', '%a, %d %b %Y %T') |
| 246 | |
| 247 | if __name__ == '__main__': |
| 248 | test() |
| 249 | |
| 250 | |