Merge lp:~mgorven/ibid/timezone-335551 into lp:~ibid-core/ibid/old-trunk-1.6

Proposed by Michael Gorven on 2010-01-06
Status: Merged
Approved by: Jonathan Hitchcock on 2010-01-07
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~mgorven/ibid/timezone-335551
Merge into: lp:~ibid-core/ibid/old-trunk-1.6
Diff against target: 169 lines (+70/-39)
1 file modified
ibid/plugins/tools.py (+70/-39)
To merge this branch: bzr merge lp:~mgorven/ibid/timezone-335551
Reviewer Review Type Date Requested Status
Jonathan Hitchcock Approve on 2010-01-07
Stefano Rivera 2010-01-06 Approve on 2010-01-07
Review via email: mp+16895@code.launchpad.net
To post a comment you must log in.
Michael Gorven (mgorven) wrote :

Better searching for timezones and custom timezones.

Stefano Rivera (stefanor) wrote :

I'd still like to see some prettier output, but yes, it looks like good improvement :)

review: Approve
Stefano Rivera (stefanor) wrote :

Oh, if you do commit anything else, the tzutc import isn't used

Stefano Rivera (stefanor) wrote :

Whoops, I withdraw that approval:

os.path.relpath(path[, start])ΒΆ
Return a relative filepath to path either from the current directory or from an optional start point.

start defaults to os.curdir. Availability: Windows, Unix.

New in version 2.6.

review: Needs Fixing
Michael Gorven (mgorven) wrote :

On Wednesday 06 January 2010 21:52:35 Stefano Rivera wrote:
> New in version 2.6.

r849

lp:~mgorven/ibid/timezone-335551 updated on 2010-01-07
849. By Michael Gorven on 2010-01-07

os.path.relpath() is only in 2.6.

Stefano Rivera (stefanor) :
review: Approve
Jonathan Hitchcock (vhata) wrote :

Aiit.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ibid/plugins/tools.py'
2--- ibid/plugins/tools.py 2010-01-02 16:01:09 +0000
3+++ ibid/plugins/tools.py 2010-01-07 08:10:24 +0000
4@@ -3,12 +3,13 @@
5 from subprocess import Popen, PIPE
6 from datetime import datetime
7 from os.path import exists, join
8+from os import walk
9
10 from dateutil.parser import parse
11 from dateutil.tz import gettz, tzutc, tzlocal, tzoffset
12
13 from ibid.plugins import Processor, match
14-from ibid.config import Option
15+from ibid.config import Option, DictOption
16 from ibid.utils import file_in_path, unicode_output, human_join, format_date, json_webservice
17 from ibid.compat import defaultdict
18
19@@ -120,6 +121,13 @@
20 MONTH_LONG = ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')
21 OTHER_STUFF = ('am', 'pm', 'st', 'nd', 'rd', 'th')
22
23+CUSTOM_ZONES = {
24+ 'PST': 'US/Pacific',
25+ 'MST': 'US/Mountain',
26+ 'CST': 'US/Central',
27+ 'EST': 'US/Eastern',
28+}
29+
30 help['timezone'] = "Converts times between timezones."
31 class TimeZone(Processor):
32 u"""when is <time> <place|timezone> in <place|timezone>
33@@ -127,13 +135,16 @@
34 feature = 'timezone'
35
36 zoneinfo = Option('zoneinfo', 'Timezone info directory', '/usr/share/zoneinfo')
37+ custom_zones = DictOption('timezones', 'Custom timezone names', CUSTOM_ZONES)
38
39 countries = {}
40- timezones = defaultdict(list)
41+ timezones = {}
42+ lowerzones = {}
43
44 def setup(self):
45 iso3166 = join(self.zoneinfo, 'iso3166.tab')
46 if exists(iso3166):
47+ self.countries = {}
48 for line in open(iso3166).readlines():
49 if not line.startswith('#'):
50 code, name = line.strip().split('\t')
51@@ -141,6 +152,7 @@
52
53 zones = join(self.zoneinfo, 'zone.tab')
54 if exists(zones):
55+ self.timezones = defaultdict(list)
56 for line in open(zones).readlines():
57 if not line.startswith('#'):
58 code, coordinates, zone = line.strip().split('\t', 2)
59@@ -148,44 +160,59 @@
60 zone, comment = zone.split('\t')
61 self.timezones[code].append(zone)
62
63+ lowerzones = {}
64+ for path, directories, filenames in walk(self.zoneinfo):
65+ if path.replace(self.zoneinfo, '').lstrip('/').split('/')[0] not in ('posix', 'right'):
66+ for filename in filenames:
67+ name = join(path, filename).replace(self.zoneinfo, '').lstrip('/')
68+ self.lowerzones[name.lower().replace('etc/', '')] = name
69+
70 def _find_timezone(self, string):
71+ for name, zonename in self.custom_zones.items():
72+ if string.lower() == name.lower():
73+ return gettz(zonename)
74+
75+ zone = gettz(string)
76+ if zone:
77+ return zone
78+
79+ zone = gettz(string.upper())
80+ if zone:
81+ return zone
82+
83+ if string.lower() in self.lowerzones:
84+ return gettz(self.lowerzones[string.lower()])
85+
86 ccode = None
87-
88- if string.upper() in ('GMT', 'UTC', 'UCT', 'ZULU'):
89- string = 'UTC'
90- zone = gettz(string)
91-
92- if not zone:
93- for code, name in self.countries.items():
94- if name.lower() == string.lower():
95- ccode = code
96- if not ccode:
97- if string.replace('.', '').upper() in self.timezones:
98- ccode = string.replace('.', '').upper()
99-
100- if ccode:
101- if len(self.timezones[ccode]) == 1:
102- zone = gettz(self.timezones[ccode][0])
103- else:
104- raise TimezoneException(u'%s has multiple timezones: %s' % (self.countries[ccode], human_join(self.timezones[ccode])))
105-
106+ for code, name in self.countries.items():
107+ if name.lower() == string.lower():
108+ ccode = code
109+ if not ccode:
110+ if string.replace('.', '').upper() in self.timezones:
111+ ccode = string.replace('.', '').upper()
112+
113+ if ccode:
114+ if len(self.timezones[ccode]) == 1:
115+ return gettz(self.timezones[ccode][0])
116 else:
117- possibles = []
118- for zones in self.timezones.values():
119- for name in zones:
120- if string.replace(' ', '_').lower() in name.lower():
121- possibles.append(name)
122-
123- if len(possibles) == 1:
124- zone = gettz(possibles[0])
125- elif len(possibles) > 1:
126- raise TimezoneException(u'Multiple timezones found: %s' % (human_join(possibles)))
127- else:
128- zone = self._geonames_lookup(string)
129- if not zone:
130- raise TimezoneException(u"I don't know about the %s timezone" % (string,))
131-
132- return zone
133+ raise TimezoneException(u'%s has multiple timezones: %s' % (self.countries[ccode], human_join(self.timezones[ccode])))
134+
135+ possibles = []
136+ for zones in self.timezones.values():
137+ for name in zones:
138+ if string.replace(' ', '_').lower() in [part.lower() for part in name.split('/')]:
139+ possibles.append(name)
140+
141+ if len(possibles) == 1:
142+ return gettz(possibles[0])
143+ elif len(possibles) > 1:
144+ raise TimezoneException(u'Multiple timezones found: %s' % (human_join(possibles)))
145+
146+ zone = self._geonames_lookup(string)
147+ if zone:
148+ return zone
149+
150+ raise TimezoneException(u"I don't know about the %s timezone" % (string,))
151
152 def _geonames_lookup(self, place):
153 search = json_webservice('http://ws.geonames.org/searchJSON', {'q': place, 'maxRows': 1})
154@@ -202,9 +229,13 @@
155 offset = timezone['rawOffset']
156 return tzoffset('UTC%s%s' % (offset>=0 and '+' or '', offset), offset*3600)
157
158- @match(r'^when\s+is\s+((?:[0-9.:/hT -]|%s)+)(?:\s+(.+))?\s+in\s+(.+)$' % '|'.join(MONTH_SHORT+MONTH_LONG+OTHER_STUFF))
159+ @match(r'^when\s+is\s+((?:[0-9.:/hT -]|%s)+)(?:\s+in)?(?:\s+(.+))?\s+in\s+(.+)$' % '|'.join(MONTH_SHORT+MONTH_LONG+OTHER_STUFF))
160 def convert(self, event, time, from_, to):
161- source = time and parse(time) or datetime.now()
162+ try:
163+ source = time and parse(time) or datetime.now()
164+ except ValueError:
165+ event.addresponse(u"That's not a real time")
166+ return
167
168 try:
169 if from_:

Subscribers

People subscribed via source and target branches