Skip to content

Commit

Permalink
Merge pull request pandas-dev#11774 from rockg/minute-tz
Browse files Browse the repository at this point in the history
BUG: Parsing offset strings with non-zero minutes was incorrect
  • Loading branch information
jreback committed Dec 7, 2015
2 parents 6ca564b + 3d7a1d4 commit ada49e1
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 40 deletions.
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v0.18.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ Bug Fixes




- Bug in parsing timezone offset strings with non-zero minutes (:issue:`11708`)



Expand Down
2 changes: 1 addition & 1 deletion pandas/src/datetime/np_datetime_strings.c
Original file line number Diff line number Diff line change
Expand Up @@ -869,7 +869,7 @@ parse_iso_8601_datetime(char *str, int len,
if (out_local != NULL) {
*out_local = 1;
// Unlike NumPy, do not change internal value to local time
*out_tzoffset = 60 * offset_hour - offset_minute;
*out_tzoffset = 60 * offset_hour + offset_minute;
}
}

Expand Down
35 changes: 0 additions & 35 deletions pandas/tests/test_tseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import pandas._period as period
import pandas.algos as algos
from pandas.core import common as com
from pandas.tseries.holiday import Holiday, SA, next_monday,USMartinLutherKingJr,USMemorialDay,AbstractHolidayCalendar
import datetime
from pandas import DateOffset

Expand Down Expand Up @@ -694,40 +693,6 @@ def test_get_period_field_raises_on_out_of_range(self):
def test_get_period_field_array_raises_on_out_of_range(self):
self.assertRaises(ValueError, period.get_period_field_arr, -1, np.empty(1), 0)

class TestFederalHolidayCalendar(tm.TestCase):

# Test for issue 10278
def test_no_mlk_before_1984(self):
class MLKCalendar(AbstractHolidayCalendar):
rules=[USMartinLutherKingJr]
holidays = MLKCalendar().holidays(start='1984', end='1988').to_pydatetime().tolist()
# Testing to make sure holiday is not incorrectly observed before 1986
self.assertEqual(holidays, [datetime.datetime(1986, 1, 20, 0, 0), datetime.datetime(1987, 1, 19, 0, 0)])

def test_memorial_day(self):
class MemorialDay(AbstractHolidayCalendar):
rules=[USMemorialDay]
holidays = MemorialDay().holidays(start='1971', end='1980').to_pydatetime().tolist()
# Fixes 5/31 error and checked manually against wikipedia
self.assertEqual(holidays, [datetime.datetime(1971, 5, 31, 0, 0), datetime.datetime(1972, 5, 29, 0, 0),
datetime.datetime(1973, 5, 28, 0, 0), datetime.datetime(1974, 5, 27, 0, 0),
datetime.datetime(1975, 5, 26, 0, 0), datetime.datetime(1976, 5, 31, 0, 0),
datetime.datetime(1977, 5, 30, 0, 0), datetime.datetime(1978, 5, 29, 0, 0),
datetime.datetime(1979, 5, 28, 0, 0)])




class TestHolidayConflictingArguments(tm.TestCase):

# GH 10217

def test_both_offset_observance_raises(self):

with self.assertRaises(NotImplementedError) as cm:
h = Holiday("Cyber Monday", month=11, day=1,
offset=[DateOffset(weekday=SA(4))], observance=next_monday)

if __name__ == '__main__':
import nose
nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],
Expand Down
34 changes: 32 additions & 2 deletions pandas/tseries/tests/test_holiday.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
USFederalHolidayCalendar, USMemorialDay, USThanksgivingDay,
nearest_workday, next_monday_or_tuesday, next_monday,
previous_friday, sunday_to_monday, Holiday, DateOffset,
MO, Timestamp, AbstractHolidayCalendar, get_calendar,
MO, SA, Timestamp, AbstractHolidayCalendar, get_calendar,
HolidayCalendarFactory, next_workday, previous_workday,
before_nearest_workday, EasterMonday, GoodFriday,
after_nearest_workday, weekend_to_monday, USLaborDay,
Expand Down Expand Up @@ -358,7 +358,37 @@ def test_after_nearest_workday(self):
self.assertEqual(after_nearest_workday(self.sa), self.mo)
self.assertEqual(after_nearest_workday(self.su), self.tu)
self.assertEqual(after_nearest_workday(self.fr), self.mo)


class TestFederalHolidayCalendar(tm.TestCase):

# Test for issue 10278
def test_no_mlk_before_1984(self):
class MLKCalendar(AbstractHolidayCalendar):
rules=[USMartinLutherKingJr]
holidays = MLKCalendar().holidays(start='1984', end='1988').to_pydatetime().tolist()
# Testing to make sure holiday is not incorrectly observed before 1986
self.assertEqual(holidays, [datetime(1986, 1, 20, 0, 0), datetime(1987, 1, 19, 0, 0)])

def test_memorial_day(self):
class MemorialDay(AbstractHolidayCalendar):
rules=[USMemorialDay]
holidays = MemorialDay().holidays(start='1971', end='1980').to_pydatetime().tolist()
# Fixes 5/31 error and checked manually against wikipedia
self.assertEqual(holidays, [datetime(1971, 5, 31, 0, 0), datetime(1972, 5, 29, 0, 0),
datetime(1973, 5, 28, 0, 0), datetime(1974, 5, 27, 0, 0),
datetime(1975, 5, 26, 0, 0), datetime(1976, 5, 31, 0, 0),
datetime(1977, 5, 30, 0, 0), datetime(1978, 5, 29, 0, 0),
datetime(1979, 5, 28, 0, 0)])

class TestHolidayConflictingArguments(tm.TestCase):

# GH 10217

def test_both_offset_observance_raises(self):

with self.assertRaises(NotImplementedError) as cm:
h = Holiday("Cyber Monday", month=11, day=1,
offset=[DateOffset(weekday=SA(4))], observance=next_monday)

if __name__ == '__main__':
nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],
Expand Down
32 changes: 31 additions & 1 deletion pandas/tseries/tests/test_tslib.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,21 @@ def test_constructor_with_stringoffset(self):
expected_repr = "Timestamp('2013-11-01 14:00:00+0900', tz='Asia/Tokyo')"
self.assertEqual(repr(result), expected_repr)
self.assertEqual(result, eval(repr(result)))

# GH11708
# This should be 2015-11-18 10:00 in UTC -> converted to Asia/Katmandu tz
result = Timestamp("2015-11-18 15:45:00+05:45", tz="Asia/Katmandu")
self.assertEqual(result.value, Timestamp("2015-11-18 10:00").value)
expected_repr = "Timestamp('2015-11-18 15:45:00+0545', tz='Asia/Katmandu')"
self.assertEqual(repr(result), expected_repr)
self.assertEqual(result, eval(repr(result)))

# This should be 2015-11-18 10:00 in UTC -> converted to Asia/Kolkata tz
result = Timestamp("2015-11-18 15:30:00+05:30", tz="Asia/Kolkata")
self.assertEqual(result.value, Timestamp("2015-11-18 10:00").value)
expected_repr = "Timestamp('2015-11-18 15:30:00+0530', tz='Asia/Kolkata')"
self.assertEqual(repr(result), expected_repr)
self.assertEqual(result, eval(repr(result)))

def test_constructor_invalid(self):
with tm.assertRaisesRegexp(TypeError, 'Cannot convert input'):
Expand Down Expand Up @@ -620,6 +635,21 @@ def test_parsers_quarterly_with_freq(self):
result, _, _ = tools.parse_time_string(date_str, freq=freq)
self.assertEqual(result, exp)

def test_parsers_timezone_minute_offsets_roundtrip(self):
#GH11708
base = to_datetime("2013-01-01 00:00:00")
dt_strings = [('2013-01-01 05:45+0545',
"Asia/Katmandu",
"Timestamp('2013-01-01 05:45:00+0545', tz='Asia/Katmandu')"),
('2013-01-01 05:30+0530',
"Asia/Kolkata",
"Timestamp('2013-01-01 05:30:00+0530', tz='Asia/Kolkata')")]

for dt_string, tz, dt_string_repr in dt_strings:
dt_time = to_datetime(dt_string)
self.assertEqual(base, dt_time)
converted_time = dt_time.tz_localize('UTC').tz_convert(tz)
self.assertEqual(dt_string_repr, repr(converted_time))

class TestArrayToDatetime(tm.TestCase):
def test_parsing_valid_dates(self):
Expand Down Expand Up @@ -721,7 +751,7 @@ def test_parsing_timezone_offsets(self):
'01-01-2013 08:00:00+08:00',
'2013-01-01T08:00:00.000000000+0800',
'2012-12-31T16:00:00.000000000-0800',
'12-31-2012 23:00:00-01:00',
'12-31-2012 23:00:00-01:00'
]

expected_output = tslib.array_to_datetime(
Expand Down

0 comments on commit ada49e1

Please sign in to comment.