codekingpro/portable-devtools
114k
1# Copyright 2016 The Kubernetes Authors.2#3# Licensed under the Apache License, Version 2.0 (the "License");4# you may not use this file except in compliance with the License.5# You may obtain a copy of the License at6#7# http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# distributed under the License is distributed on an "AS IS" BASIS,11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12# See the License for the specific language governing permissions and13# limitations under the License.14 15import unittest16from datetime import datetime17 18from .dateutil import UTC, TimezoneInfo, format_rfc3339, parse_rfc333919 20 21class DateUtilTest(unittest.TestCase):22 23 def _parse_rfc3339_test(self, st, y, m, d, h, mn, s, us):24 actual = parse_rfc3339(st)25 expected = datetime(y, m, d, h, mn, s, us, UTC)26 self.assertEqual(expected, actual)27 28 def test_parse_rfc3339(self):29 self._parse_rfc3339_test("2017-07-25T04:44:21Z",30 2017, 7, 25, 4, 44, 21, 0)31 self._parse_rfc3339_test("2017-07-25 04:44:21Z",32 2017, 7, 25, 4, 44, 21, 0)33 self._parse_rfc3339_test("2017-07-25T04:44:21",34 2017, 7, 25, 4, 44, 21, 0)35 self._parse_rfc3339_test("2017-07-25T04:44:21z",36 2017, 7, 25, 4, 44, 21, 0)37 self._parse_rfc3339_test("2017-07-25T04:44:21+03:00",38 2017, 7, 25, 1, 44, 21, 0)39 self._parse_rfc3339_test("2017-07-25T04:44:21-03:00",40 2017, 7, 25, 7, 44, 21, 0)41 42 self._parse_rfc3339_test("2017-07-25T04:44:21,005Z",43 2017, 7, 25, 4, 44, 21, 5000)44 self._parse_rfc3339_test("2017-07-25T04:44:21.005Z",45 2017, 7, 25, 4, 44, 21, 5000)46 self._parse_rfc3339_test("2017-07-25 04:44:21.0050Z",47 2017, 7, 25, 4, 44, 21, 5000)48 self._parse_rfc3339_test("2017-07-25T04:44:21.5",49 2017, 7, 25, 4, 44, 21, 500000)50 self._parse_rfc3339_test("2017-07-25T04:44:21.005z",51 2017, 7, 25, 4, 44, 21, 5000)52 self._parse_rfc3339_test("2017-07-25T04:44:21.005+03:00",53 2017, 7, 25, 1, 44, 21, 5000)54 self._parse_rfc3339_test("2017-07-25T04:44:21.005-03:00",55 2017, 7, 25, 7, 44, 21, 5000)56 57 def test_format_rfc3339(self):58 self.assertEqual(59 format_rfc3339(datetime(2017, 7, 25, 4, 44, 21, 0, UTC)),60 "2017-07-25T04:44:21Z")61 self.assertEqual(62 format_rfc3339(datetime(2017, 7, 25, 4, 44, 21, 0,63 TimezoneInfo(2, 0))),64 "2017-07-25T02:44:21Z")65 self.assertEqual(66 format_rfc3339(datetime(2017, 7, 25, 4, 44, 21, 0,67 TimezoneInfo(-2, 30))),68 "2017-07-25T07:14:21Z")69 70 def test_parse_rfc3339_invalid_formats(self):71 """Test that invalid RFC3339 formats raise ValueError"""72 invalid_inputs = [73 "2025-13-02T13:37:00Z", # Invalid month74 "2025-12-32T13:37:00Z", # Invalid day75 "2025-12-02T25:00:00Z", # Invalid hour76 "2025-12-02T13:60:00Z", # Invalid minute77 "2025-12-02T13:37:60Z", # Invalid second78 "not-a-valid-date", # Completely invalid79 "", # Empty string80 "2025-12-02Z13:37:00", # Timezone before time81 ]82 83 for invalid_input in invalid_inputs:84 with self.assertRaises(ValueError):85 parse_rfc3339(invalid_input)86 87 88 89 def test_parse_rfc3339_with_whitespace(self):90 """Test that leading/trailing whitespace is handled"""91 actual = parse_rfc3339(" 2017-07-25T04:44:21Z ")92 expected = datetime(2017, 7, 25, 4, 44, 21, 0, UTC)93 self.assertEqual(expected, actual)94 95 def test_parse_rfc3339_error_message_clarity(self):96 """Test that error messages are clear and helpful"""97 try:98 parse_rfc3339("invalid-date-format")99 except ValueError as e:100 error_msg = str(e)101 # Verify error message contains helpful information102 self.assertIn("Invalid RFC3339", error_msg)103 self.assertIn("YYYY-MM-DD", error_msg)104 self.assertIn("expected", error_msg)105 