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

Proposed by Michael Gorven
Status: Merged
Approved by: Jonathan Hitchcock
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
Stefano Rivera Approve
Review via email: mp+16895@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Michael Gorven (mgorven) wrote :

Better searching for timezones and custom timezones.

Revision history for this message
Stefano Rivera (stefanor) wrote :

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

review: Approve
Revision history for this message
Stefano Rivera (stefanor) wrote :

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

Revision history for this message
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
Revision history for this message
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
849. By Michael Gorven

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

Revision history for this message
Stefano Rivera (stefanor) :
review: Approve
Revision history for this message
Jonathan Hitchcock (vhata) wrote :

Aiit.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'ibid/plugins/tools.py'
--- ibid/plugins/tools.py 2010-01-02 16:01:09 +0000
+++ ibid/plugins/tools.py 2010-01-07 08:10:24 +0000
@@ -3,12 +3,13 @@
3from subprocess import Popen, PIPE3from subprocess import Popen, PIPE
4from datetime import datetime4from datetime import datetime
5from os.path import exists, join5from os.path import exists, join
6from os import walk
67
7from dateutil.parser import parse8from dateutil.parser import parse
8from dateutil.tz import gettz, tzutc, tzlocal, tzoffset9from dateutil.tz import gettz, tzutc, tzlocal, tzoffset
910
10from ibid.plugins import Processor, match11from ibid.plugins import Processor, match
11from ibid.config import Option12from ibid.config import Option, DictOption
12from ibid.utils import file_in_path, unicode_output, human_join, format_date, json_webservice13from ibid.utils import file_in_path, unicode_output, human_join, format_date, json_webservice
13from ibid.compat import defaultdict14from ibid.compat import defaultdict
1415
@@ -120,6 +121,13 @@
120MONTH_LONG = ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')121MONTH_LONG = ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')
121OTHER_STUFF = ('am', 'pm', 'st', 'nd', 'rd', 'th')122OTHER_STUFF = ('am', 'pm', 'st', 'nd', 'rd', 'th')
122123
124CUSTOM_ZONES = {
125 'PST': 'US/Pacific',
126 'MST': 'US/Mountain',
127 'CST': 'US/Central',
128 'EST': 'US/Eastern',
129}
130
123help['timezone'] = "Converts times between timezones."131help['timezone'] = "Converts times between timezones."
124class TimeZone(Processor):132class TimeZone(Processor):
125 u"""when is <time> <place|timezone> in <place|timezone>133 u"""when is <time> <place|timezone> in <place|timezone>
@@ -127,13 +135,16 @@
127 feature = 'timezone'135 feature = 'timezone'
128136
129 zoneinfo = Option('zoneinfo', 'Timezone info directory', '/usr/share/zoneinfo')137 zoneinfo = Option('zoneinfo', 'Timezone info directory', '/usr/share/zoneinfo')
138 custom_zones = DictOption('timezones', 'Custom timezone names', CUSTOM_ZONES)
130139
131 countries = {}140 countries = {}
132 timezones = defaultdict(list)141 timezones = {}
142 lowerzones = {}
133143
134 def setup(self):144 def setup(self):
135 iso3166 = join(self.zoneinfo, 'iso3166.tab')145 iso3166 = join(self.zoneinfo, 'iso3166.tab')
136 if exists(iso3166):146 if exists(iso3166):
147 self.countries = {}
137 for line in open(iso3166).readlines():148 for line in open(iso3166).readlines():
138 if not line.startswith('#'):149 if not line.startswith('#'):
139 code, name = line.strip().split('\t')150 code, name = line.strip().split('\t')
@@ -141,6 +152,7 @@
141152
142 zones = join(self.zoneinfo, 'zone.tab')153 zones = join(self.zoneinfo, 'zone.tab')
143 if exists(zones):154 if exists(zones):
155 self.timezones = defaultdict(list)
144 for line in open(zones).readlines():156 for line in open(zones).readlines():
145 if not line.startswith('#'):157 if not line.startswith('#'):
146 code, coordinates, zone = line.strip().split('\t', 2)158 code, coordinates, zone = line.strip().split('\t', 2)
@@ -148,44 +160,59 @@
148 zone, comment = zone.split('\t')160 zone, comment = zone.split('\t')
149 self.timezones[code].append(zone)161 self.timezones[code].append(zone)
150162
163 lowerzones = {}
164 for path, directories, filenames in walk(self.zoneinfo):
165 if path.replace(self.zoneinfo, '').lstrip('/').split('/')[0] not in ('posix', 'right'):
166 for filename in filenames:
167 name = join(path, filename).replace(self.zoneinfo, '').lstrip('/')
168 self.lowerzones[name.lower().replace('etc/', '')] = name
169
151 def _find_timezone(self, string):170 def _find_timezone(self, string):
171 for name, zonename in self.custom_zones.items():
172 if string.lower() == name.lower():
173 return gettz(zonename)
174
175 zone = gettz(string)
176 if zone:
177 return zone
178
179 zone = gettz(string.upper())
180 if zone:
181 return zone
182
183 if string.lower() in self.lowerzones:
184 return gettz(self.lowerzones[string.lower()])
185
152 ccode = None186 ccode = None
153187 for code, name in self.countries.items():
154 if string.upper() in ('GMT', 'UTC', 'UCT', 'ZULU'):188 if name.lower() == string.lower():
155 string = 'UTC'189 ccode = code
156 zone = gettz(string)190 if not ccode:
157191 if string.replace('.', '').upper() in self.timezones:
158 if not zone:192 ccode = string.replace('.', '').upper()
159 for code, name in self.countries.items():193
160 if name.lower() == string.lower():194 if ccode:
161 ccode = code195 if len(self.timezones[ccode]) == 1:
162 if not ccode:196 return gettz(self.timezones[ccode][0])
163 if string.replace('.', '').upper() in self.timezones:
164 ccode = string.replace('.', '').upper()
165
166 if ccode:
167 if len(self.timezones[ccode]) == 1:
168 zone = gettz(self.timezones[ccode][0])
169 else:
170 raise TimezoneException(u'%s has multiple timezones: %s' % (self.countries[ccode], human_join(self.timezones[ccode])))
171
172 else:197 else:
173 possibles = []198 raise TimezoneException(u'%s has multiple timezones: %s' % (self.countries[ccode], human_join(self.timezones[ccode])))
174 for zones in self.timezones.values():199
175 for name in zones:200 possibles = []
176 if string.replace(' ', '_').lower() in name.lower():201 for zones in self.timezones.values():
177 possibles.append(name)202 for name in zones:
178203 if string.replace(' ', '_').lower() in [part.lower() for part in name.split('/')]:
179 if len(possibles) == 1:204 possibles.append(name)
180 zone = gettz(possibles[0])205
181 elif len(possibles) > 1:206 if len(possibles) == 1:
182 raise TimezoneException(u'Multiple timezones found: %s' % (human_join(possibles)))207 return gettz(possibles[0])
183 else:208 elif len(possibles) > 1:
184 zone = self._geonames_lookup(string)209 raise TimezoneException(u'Multiple timezones found: %s' % (human_join(possibles)))
185 if not zone:210
186 raise TimezoneException(u"I don't know about the %s timezone" % (string,))211 zone = self._geonames_lookup(string)
187212 if zone:
188 return zone213 return zone
214
215 raise TimezoneException(u"I don't know about the %s timezone" % (string,))
189216
190 def _geonames_lookup(self, place):217 def _geonames_lookup(self, place):
191 search = json_webservice('http://ws.geonames.org/searchJSON', {'q': place, 'maxRows': 1})218 search = json_webservice('http://ws.geonames.org/searchJSON', {'q': place, 'maxRows': 1})
@@ -202,9 +229,13 @@
202 offset = timezone['rawOffset']229 offset = timezone['rawOffset']
203 return tzoffset('UTC%s%s' % (offset>=0 and '+' or '', offset), offset*3600)230 return tzoffset('UTC%s%s' % (offset>=0 and '+' or '', offset), offset*3600)
204231
205 @match(r'^when\s+is\s+((?:[0-9.:/hT -]|%s)+)(?:\s+(.+))?\s+in\s+(.+)$' % '|'.join(MONTH_SHORT+MONTH_LONG+OTHER_STUFF))232 @match(r'^when\s+is\s+((?:[0-9.:/hT -]|%s)+)(?:\s+in)?(?:\s+(.+))?\s+in\s+(.+)$' % '|'.join(MONTH_SHORT+MONTH_LONG+OTHER_STUFF))
206 def convert(self, event, time, from_, to):233 def convert(self, event, time, from_, to):
207 source = time and parse(time) or datetime.now()234 try:
235 source = time and parse(time) or datetime.now()
236 except ValueError:
237 event.addresponse(u"That's not a real time")
238 return
208239
209 try:240 try:
210 if from_:241 if from_:

Subscribers

People subscribed via source and target branches