Skip to content

Commit 667220a

Browse files
committed
Merge remote-tracking branch 'chang/fixedoffset'
* chang/fixedoffset: BUG: more fixedoffset occurrences #1928 BUG: no zone in tzinfo #1838
2 parents d5e075e + c0d79bc commit 667220a

File tree

6 files changed

+50
-12
lines changed

6 files changed

+50
-12
lines changed

pandas/io/pytables.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,10 @@ def _write_index(self, group, key, index):
579579
node._v_attrs.freq = index.freq
580580

581581
if hasattr(index, 'tz') and index.tz is not None:
582-
node._v_attrs.tz = index.tz.zone
582+
zone = lib.get_timezone(index.tz)
583+
if zone is None:
584+
zone = lib.tot_seconds(index.tz.utcoffset())
585+
node._v_attrs.tz = zone
583586

584587
def _read_index(self, group, key):
585588
variety = getattr(group._v_attrs, '%s_variety' % key)
@@ -1159,4 +1162,3 @@ def f(values, freq=None, tz=None):
11591162
tz=tz)
11601163
return f
11611164
return klass
1162-

pandas/io/tests/test_pytables.py

+13
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,19 @@ def test_timezones(self):
380380
store.close()
381381
os.remove(self.scratchpath)
382382

383+
def test_fixed_offset_tz(self):
384+
rng = date_range('1/1/2000 00:00:00-07:00', '1/30/2000 00:00:00-07:00')
385+
frame = DataFrame(np.random.randn(len(rng), 4), index=rng)
386+
try:
387+
store = HDFStore(self.scratchpath)
388+
store['frame'] = frame
389+
recons = store['frame']
390+
self.assert_(recons.index.equals(rng))
391+
self.assertEquals(rng.tz, recons.index.tz)
392+
finally:
393+
store.close()
394+
os.remove(self.scratchpath)
395+
383396
def test_store_hierarchical(self):
384397
index = MultiIndex(levels=[['foo', 'bar', 'baz', 'qux'],
385398
['one', 'two', 'three']],

pandas/src/datetime.pyx

+14-6
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,14 @@ class Timestamp(_Timestamp):
107107
try:
108108
result += self.strftime('%z')
109109
if self.tzinfo:
110-
result += self.strftime(' %%Z, tz=%s' % self.tzinfo.zone)
110+
zone = _get_zone(self.tzinfo)
111+
result += self.strftime(' %%Z, tz=%s' % zone)
111112
except ValueError:
112113
year2000 = self.replace(year=2000)
113114
result += year2000.strftime('%z')
114115
if self.tzinfo:
115-
result += year2000.strftime(' %%Z, tz=%s' % self.tzinfo.zone)
116+
zone = _get_zone(self.tzinfo)
117+
result += year2000.strftime(' %%Z, tz=%s' % zone)
116118

117119
return '<Timestamp: %s>' % result
118120

@@ -615,6 +617,9 @@ cpdef convert_to_tsobject(object ts, object tz=None):
615617

616618
return obj
617619

620+
def get_timezone(tz):
621+
return _get_zone(tz)
622+
618623
cdef inline bint _is_utc(object tz):
619624
return tz is UTC or isinstance(tz, _du_utc)
620625

@@ -911,7 +916,7 @@ def tz_convert(ndarray[int64_t] vals, object tz1, object tz2):
911916

912917
# Convert to UTC
913918

914-
if tz1.zone != 'UTC':
919+
if _get_zone(tz1) != 'UTC':
915920
utc_dates = np.empty(n, dtype=np.int64)
916921
deltas = _get_deltas(tz1)
917922
trans = _get_transitions(tz1)
@@ -929,7 +934,7 @@ def tz_convert(ndarray[int64_t] vals, object tz1, object tz2):
929934
else:
930935
utc_dates = vals
931936

932-
if tz2.zone == 'UTC':
937+
if _get_zone(tz2) == 'UTC':
933938
return utc_dates
934939

935940
# Convert UTC to other timezone
@@ -968,7 +973,7 @@ def tz_convert_single(int64_t val, object tz1, object tz2):
968973

969974
# Convert to UTC
970975

971-
if tz1.zone != 'UTC':
976+
if _get_zone(tz1) != 'UTC':
972977
deltas = _get_deltas(tz1)
973978
trans = _get_transitions(tz1)
974979
pos = trans.searchsorted(val) - 1
@@ -979,7 +984,7 @@ def tz_convert_single(int64_t val, object tz1, object tz2):
979984
else:
980985
utc_date = val
981986

982-
if tz2.zone == 'UTC':
987+
if _get_zone(tz2) == 'UTC':
983988
return utc_date
984989

985990
# Convert UTC to other timezone
@@ -1026,6 +1031,9 @@ cdef double total_seconds(object td): # Python 2.6 compat
10261031
return ((td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) //
10271032
10**6)
10281033

1034+
def tot_seconds(td):
1035+
return total_seconds(td)
1036+
10291037
cpdef ndarray _unbox_utcoffsets(object transinfo):
10301038
cdef:
10311039
Py_ssize_t i, sz

pandas/tseries/index.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1220,7 +1220,7 @@ def equals(self, other):
12201220
if self.tz is not None:
12211221
if other.tz is None:
12221222
return False
1223-
same_zone = self.tz.zone == other.tz.zone
1223+
same_zone = lib.get_timezone(self.tz) == lib.get_timezone(other.tz)
12241224
else:
12251225
if other.tz is not None:
12261226
return False

pandas/tseries/tests/test_timezones.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def tzname(self, dt):
6060
def dst(self, dt):
6161
return timedelta(0)
6262

63-
fixed_off = FixedOffset(-4200, '-07:00')
63+
fixed_off = FixedOffset(-420, '-07:00')
6464

6565
class TestTimeZoneSupport(unittest.TestCase):
6666

@@ -152,6 +152,19 @@ def test_create_with_tz(self):
152152
stamp = Timestamp('3/11/2012 05:00').tz_localize('utc')
153153
self.assertEquals(utc_stamp.hour, 5)
154154

155+
def test_create_with_fixed_tz(self):
156+
off = FixedOffset(420, '+07:00')
157+
start = datetime(2012, 3, 11, 5, 0, 0, tzinfo=off)
158+
end = datetime(2012, 6, 11, 5, 0, 0, tzinfo=off)
159+
rng = date_range(start=start, end=end)
160+
self.assertEqual(off, rng.tz)
161+
162+
rng2 = date_range(start, periods=len(rng), tz=off)
163+
self.assert_(rng.equals(rng2))
164+
165+
rng3 = date_range('3/11/2012 05:00:00+07:00', '6/11/2012 05:00:00+07:00')
166+
self.assert_((rng.values == rng3.values).all())
167+
155168
def test_date_range_localize(self):
156169
rng = date_range('3/11/2012 03:00', periods=15, freq='H', tz='US/Eastern')
157170
rng2 = DatetimeIndex(['3/11/2012 03:00', '3/11/2012 04:00'],

pandas/tseries/tools.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,11 @@
2121
print 'Please install python-dateutil via easy_install or some method!'
2222
raise # otherwise a 2nd import won't show the message
2323

24-
2524
def _infer_tzinfo(start, end):
2625
def _infer(a, b):
2726
tz = a.tzinfo
2827
if b and b.tzinfo:
29-
assert(tz.zone == b.tzinfo.zone)
28+
assert(lib.get_timezone(tz) == lib.get_timezone(b.tzinfo))
3029
return tz
3130
tz = None
3231
if start is not None:
@@ -40,6 +39,9 @@ def _maybe_get_tz(tz):
4039
if isinstance(tz, (str, unicode)):
4140
import pytz
4241
tz = pytz.timezone(tz)
42+
if com.is_integer(tz):
43+
import pytz
44+
tz = pytz.FixedOffset(tz / 60)
4345
return tz
4446

4547

0 commit comments

Comments
 (0)