• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zopefoundation / DateTime / 3655319845

pending completion
3655319845

push

github

Michael Howitz
Fix GHA: ubuntu-latest no longer contains Python 2.7 up to 3.6

260 of 336 branches covered (77.38%)

Branch coverage included in aggregate %.

1405 of 1550 relevant lines covered (90.65%)

0.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.95
/src/DateTime/tests/test_datetime.py
1
##############################################################################
2
#
3
# Copyright (c) 2003 Zope Foundation and Contributors.
4
# All Rights Reserved.
5
#
6
# This software is subject to the provisions of the Zope Public License,
7
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
8
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
# FOR A PARTICULAR PURPOSE.
12
#
13
##############################################################################
14

15
import math
1✔
16
import os
1✔
17
import platform
1✔
18
import sys
1✔
19
import time
1✔
20
import unittest
1✔
21
from datetime import date
1✔
22
from datetime import datetime
1✔
23
from datetime import timedelta
1✔
24
from datetime import tzinfo
1✔
25

26
import pytz
1✔
27

28
from DateTime import DateTime
1✔
29
from DateTime.DateTime import _findLocalTimeZoneName
1✔
30

31

32
if sys.version_info > (3, ):  # pragma: PY3
1✔
33
    import pickle
1✔
34
    unicode = str
1✔
35
    PY3K = True
1✔
36
else:  # pragma: PY2
37
    import cPickle as pickle
38
    PY3K = False
39

40
try:
1✔
41
    __file__
1✔
42
except NameError:   # pragma: no cover
43
    f = sys.argv[0]
44
else:
45
    f = __file__
1✔
46

47
IS_PYPY = getattr(platform, 'python_implementation', lambda: None)() == 'PyPy'
1!
48

49
DATADIR = os.path.dirname(os.path.abspath(f))
1✔
50
del f
1✔
51

52
ZERO = timedelta(0)
1✔
53

54

55
class FixedOffset(tzinfo):
1✔
56
    """Fixed offset in minutes east from UTC."""
57

58
    def __init__(self, offset, name):
1✔
59
        self.__offset = timedelta(minutes=offset)
1✔
60
        self.__name = name
1✔
61

62
    def utcoffset(self, dt):
1✔
63
        return self.__offset
1✔
64

65
    def tzname(self, dt):
1✔
66
        return self.__name
×
67

68
    def dst(self, dt):
1✔
69
        return ZERO
×
70

71

72
class DateTimeTests(unittest.TestCase):
1✔
73

74
    def _compare(self, dt1, dt2):
1✔
75
        '''Compares the internal representation of dt1 with
76
        the representation in dt2.  Allows sub-millisecond variations.
77
        Primarily for testing.'''
78
        self.assertEqual(round(dt1._t, 3), round(dt2._t, 3))
1✔
79
        self.assertEqual(round(dt1._d, 9), round(dt2._d, 9))
1✔
80
        self.assertEqual(round(dt1.time, 9), round(dt2.time, 9))
1✔
81
        self.assertEqual(dt1.millis(), dt2.millis())
1✔
82
        self.assertEqual(dt1._micros, dt2._micros)
1✔
83

84
    def testBug1203(self):
1✔
85
        # 01:59:60 occurred in old DateTime
86
        dt = DateTime(7200, 'GMT')
1✔
87
        self.assertTrue(str(dt).find('60') < 0, dt)
1✔
88

89
    def testDSTInEffect(self):
1✔
90
        # Checks GMT offset for a DST date in the US/Eastern time zone
91
        dt = DateTime(2000, 5, 9, 15, 0, 0, 'US/Eastern')
1✔
92
        self.assertEqual(dt.toZone('GMT').hour(), 19,
1✔
93
                         (dt, dt.toZone('GMT')))
94

95
    def testDSTNotInEffect(self):
1✔
96
        # Checks GMT offset for a non-DST date in the US/Eastern time zone
97
        dt = DateTime(2000, 11, 9, 15, 0, 0, 'US/Eastern')
1✔
98
        self.assertEqual(dt.toZone('GMT').hour(), 20,
1✔
99
                         (dt, dt.toZone('GMT')))
100

101
    def testAddPrecision(self):
1✔
102
        # Precision of serial additions
103
        dt = DateTime()
1✔
104
        self.assertEqual(str(dt + 0.10 + 3.14 + 6.76 - 10), str(dt),
1✔
105
                         dt)
106
        # checks problem reported in
107
        # https://github.com/zopefoundation/DateTime/issues/41
108
        dt = DateTime(2038, 10, 7, 8, 52, 44.959840, "UTC")
1✔
109
        self.assertEqual(str(dt + 0.10 + 3.14 + 6.76 - 10), str(dt),
1✔
110
                         dt)
111

112
    def testConsistentSecondMicroRounding(self):
1✔
113
        dt = DateTime(2038, 10, 7, 8, 52, 44.9598398, "UTC")
1✔
114
        self.assertEqual(int(dt.second() * 1000000),
1✔
115
                         dt.micros() % 60000000)
116

117
    def testConstructor3(self):
1✔
118
        # Constructor from date/time string
119
        dt = DateTime()
1✔
120
        dt1s = '%d/%d/%d %d:%d:%f %s' % (
1✔
121
            dt.year(),
122
            dt.month(),
123
            dt.day(),
124
            dt.hour(),
125
            dt.minute(),
126
            dt.second(),
127
            dt.timezone())
128
        dt1 = DateTime(dt1s)
1✔
129
        # Compare representations as it's the
130
        # only way to compare the dates to the same accuracy
131
        self.assertEqual(repr(dt), repr(dt1))
1✔
132

133
    def testConstructor4(self):
1✔
134
        # Constructor from time float
135
        dt = DateTime()
1✔
136
        dt1 = DateTime(float(dt))
1✔
137
        self._compare(dt, dt1)
1✔
138

139
    def testConstructor5(self):
1✔
140
        # Constructor from time float and timezone
141
        dt = DateTime()
1✔
142
        dt1 = DateTime(float(dt), dt.timezone())
1✔
143
        self.assertEqual(str(dt), str(dt1), (dt, dt1))
1✔
144
        dt1 = DateTime(float(dt), unicode(dt.timezone()))
1✔
145
        self.assertEqual(str(dt), str(dt1), (dt, dt1))
1✔
146

147
    def testConstructor6(self):
1✔
148
        # Constructor from year and julian date
149
        # This test must normalize the time zone, or it *will* break when
150
        # DST changes!
151
        dt1 = DateTime(2000, 5.500000578705)
1✔
152
        dt = DateTime('2000/1/5 12:00:00.050 pm %s' % dt1.localZone())
1✔
153
        self._compare(dt, dt1)
1✔
154

155
    def testConstructor7(self):
1✔
156
        # Constructor from parts
157
        dt = DateTime()
1✔
158
        dt1 = DateTime(
1✔
159
            dt.year(),
160
            dt.month(),
161
            dt.day(),
162
            dt.hour(),
163
            dt.minute(),
164
            dt.second(),
165
            dt.timezone())
166
        # Compare representations as it's the
167
        # only way to compare the dates to the same accuracy
168
        self.assertEqual(repr(dt), repr(dt1))
1✔
169

170
    def testDayOfWeek(self):
1✔
171
        # Compare to the datetime.date value to make it locale independent
172
        expected = date(2000, 6, 16).strftime('%A')
1✔
173
        # strftime() used to always be passed a day of week of 0
174
        dt = DateTime('2000/6/16')
1✔
175
        s = dt.strftime('%A')
1✔
176
        self.assertEqual(s, expected, (dt, s))
1✔
177

178
    def testOldDate(self):
1✔
179
        # Fails when an 1800 date is displayed with negative signs
180
        dt = DateTime('1830/5/6 12:31:46.213 pm')
1✔
181
        dt1 = dt.toZone('GMT+6')
1✔
182
        self.assertTrue(str(dt1).find('-') < 0, (dt, dt1))
1✔
183

184
    def testSubtraction(self):
1✔
185
        # Reconstruction of a DateTime from its parts, with subtraction
186
        # this also tests the accuracy of addition and reconstruction
187
        dt = DateTime()
1✔
188
        dt1 = dt - 3.141592653
1✔
189
        dt2 = DateTime(
1✔
190
            dt.year(),
191
            dt.month(),
192
            dt.day(),
193
            dt.hour(),
194
            dt.minute(),
195
            dt.second())
196
        dt3 = dt2 - 3.141592653
1✔
197
        self.assertEqual(dt1, dt3, (dt, dt1, dt2, dt3))
1✔
198

199
    def testTZ1add(self):
1✔
200
        # Time zone manipulation: add to a date
201
        dt = DateTime('1997/3/8 1:45am GMT-4')
1✔
202
        dt1 = DateTime('1997/3/9 1:45pm GMT+8')
1✔
203
        self.assertTrue((dt + 1.0).equalTo(dt1))
1✔
204

205
    def testTZ1sub(self):
1✔
206
        # Time zone manipulation: subtract from a date
207
        dt = DateTime('1997/3/8 1:45am GMT-4')
1✔
208
        dt1 = DateTime('1997/3/9 1:45pm GMT+8')
1✔
209
        self.assertTrue((dt1 - 1.0).equalTo(dt))
1✔
210

211
    def testTZ1diff(self):
1✔
212
        # Time zone manipulation: diff two dates
213
        dt = DateTime('1997/3/8 1:45am GMT-4')
1✔
214
        dt1 = DateTime('1997/3/9 1:45pm GMT+8')
1✔
215
        self.assertEqual(dt1 - dt, 1.0, (dt, dt1))
1✔
216

217
    def test_compare_methods(self):
1✔
218
        # Compare two dates using several methods
219
        dt = DateTime('1997/1/1')
1✔
220
        dt1 = DateTime('1997/2/2')
1✔
221
        self.assertTrue(dt1.greaterThan(dt))
1✔
222
        self.assertTrue(dt1.greaterThanEqualTo(dt))
1✔
223
        self.assertTrue(dt.lessThan(dt1))
1✔
224
        self.assertTrue(dt.lessThanEqualTo(dt1))
1✔
225
        self.assertTrue(dt.notEqualTo(dt1))
1✔
226
        self.assertFalse(dt.equalTo(dt1))
1✔
227

228
    def test_compare_methods_none(self):
1✔
229
        # Compare a date to None
230
        dt = DateTime('1997/1/1')
1✔
231
        self.assertTrue(dt.greaterThan(None))
1✔
232
        self.assertTrue(dt.greaterThanEqualTo(None))
1✔
233
        self.assertFalse(dt.lessThan(None))
1✔
234
        self.assertFalse(dt.lessThanEqualTo(None))
1✔
235
        self.assertTrue(dt.notEqualTo(None))
1✔
236
        self.assertFalse(dt.equalTo(None))
1✔
237

238
    def test_pickle(self):
1✔
239
        dt = DateTime()
1✔
240
        data = pickle.dumps(dt, 1)
1✔
241
        new = pickle.loads(data)
1✔
242
        for key in DateTime.__slots__:
1✔
243
            self.assertEqual(getattr(dt, key), getattr(new, key))
1✔
244

245
    def test_pickle_with_tz(self):
1✔
246
        dt = DateTime('2002/5/2 8:00am GMT+8')
1✔
247
        data = pickle.dumps(dt, 1)
1✔
248
        new = pickle.loads(data)
1✔
249
        for key in DateTime.__slots__:
1✔
250
            self.assertEqual(getattr(dt, key), getattr(new, key))
1✔
251

252
    def test_pickle_with_numerical_tz(self):
1✔
253
        for dt_str in ('2007/01/02 12:34:56.789 +0300',
1✔
254
                       '2007/01/02 12:34:56.789 +0430',
255
                       '2007/01/02 12:34:56.789 -1234'):
256
            dt = DateTime(dt_str)
1✔
257
            data = pickle.dumps(dt, 1)
1✔
258
            new = pickle.loads(data)
1✔
259
            for key in DateTime.__slots__:
1✔
260
                self.assertEqual(getattr(dt, key), getattr(new, key))
1✔
261

262
    def test_pickle_with_micros(self):
1✔
263
        dt = DateTime('2002/5/2 8:00:14.123 GMT+8')
1✔
264
        data = pickle.dumps(dt, 1)
1✔
265
        new = pickle.loads(data)
1✔
266
        for key in DateTime.__slots__:
1✔
267
            self.assertEqual(getattr(dt, key), getattr(new, key))
1✔
268

269
    def test_pickle_old(self):
1✔
270
        dt = DateTime('2002/5/2 8:00am GMT+0')
1✔
271
        data = (
1✔
272
            '(cDateTime.DateTime\nDateTime\nq\x01Noq\x02}q\x03(U\x05'
273
            '_amonq\x04U\x03Mayq\x05U\x05_adayq\x06U\x03Thuq\x07U\x05_pmonq'
274
            '\x08h\x05U\x05_hourq\tK\x08U\x05_fmonq\nh\x05U\x05_pdayq\x0bU'
275
            '\x04Thu.q\x0cU\x05_fdayq\rU\x08Thursdayq\x0eU\x03_pmq\x0fU\x02amq'
276
            '\x10U\x02_tq\x11GA\xcehy\x00\x00\x00\x00U\x07_minuteq\x12K\x00U'
277
            '\x07_microsq\x13L1020326400000000L\nU\x02_dq\x14G@\xe2\x12j\xaa'
278
            '\xaa\xaa\xabU\x07_secondq\x15G\x00\x00\x00\x00\x00\x00\x00\x00U'
279
            '\x03_tzq\x16U\x05GMT+0q\x17U\x06_monthq\x18K\x05U'
280
            '\x0f_timezone_naiveq\x19I00\nU\x04_dayq\x1aK\x02U\x05_yearq'
281
            '\x1bM\xd2\x07U\x08_nearsecq\x1cG\x00\x00\x00\x00\x00\x00\x00'
282
            '\x00U\x07_pmhourq\x1dK\x08U\n_dayoffsetq\x1eK\x04U\x04timeq'
283
            '\x1fG?\xd5UUUV\x00\x00ub.')
284
        if PY3K:
1!
285
            data = data.encode('latin-1')
1✔
286
        new = pickle.loads(data)
1✔
287
        for key in DateTime.__slots__:
1✔
288
            self.assertEqual(getattr(dt, key), getattr(new, key))
1✔
289

290
    def test_pickle_old_without_micros(self):
1✔
291
        dt = DateTime('2002/5/2 8:00am GMT+0')
1✔
292
        data = (
1✔
293
            '(cDateTime.DateTime\nDateTime\nq\x01Noq\x02}q\x03(U\x05'
294
            '_amonq\x04U\x03Mayq\x05U\x05_adayq\x06U\x03Thuq\x07U\x05_pmonq'
295
            '\x08h\x05U\x05_hourq\tK\x08U\x05_fmonq\nh\x05U\x05_pdayq\x0bU'
296
            '\x04Thu.q\x0cU\x05_fdayq\rU\x08Thursdayq\x0eU\x03_pmq\x0fU'
297
            '\x02amq\x10U\x02_tq\x11GA\xcehy\x00\x00\x00\x00U\x07_minuteq'
298
            '\x12K\x00U\x02_dq\x13G@\xe2\x12j\xaa\xaa\xaa\xabU\x07_secondq'
299
            '\x14G\x00\x00\x00\x00\x00\x00\x00\x00U\x03_tzq\x15U\x05GMT+0q'
300
            '\x16U\x06_monthq\x17K\x05U\x0f_timezone_naiveq\x18I00\nU'
301
            '\x04_dayq\x19K\x02U\x05_yearq\x1aM\xd2\x07U\x08_nearsecq'
302
            '\x1bG\x00\x00\x00\x00\x00\x00\x00\x00U\x07_pmhourq\x1cK\x08U'
303
            '\n_dayoffsetq\x1dK\x04U\x04timeq\x1eG?\xd5UUUV\x00\x00ub.')
304
        if PY3K:
1!
305
            data = data.encode('latin-1')
1✔
306
        new = pickle.loads(data)
1✔
307
        for key in DateTime.__slots__:
1✔
308
            self.assertEqual(getattr(dt, key), getattr(new, key))
1✔
309

310
    def testTZ2(self):
1✔
311
        # Time zone manipulation test 2
312
        dt = DateTime()
1✔
313
        dt1 = dt.toZone('GMT')
1✔
314
        s = dt.second()
1✔
315
        s1 = dt1.second()
1✔
316
        self.assertEqual(s, s1, (dt, dt1, s, s1))
1✔
317

318
    def testTZDiffDaylight(self):
1✔
319
        # Diff dates across daylight savings dates
320
        dt = DateTime('2000/6/8 1:45am US/Eastern')
1✔
321
        dt1 = DateTime('2000/12/8 12:45am US/Eastern')
1✔
322
        self.assertEqual(dt1 - dt, 183, (dt, dt1, dt1 - dt))
1✔
323

324
    def testY10KDate(self):
1✔
325
        # Comparison of a Y10K date and a Y2K date
326
        dt = DateTime('10213/09/21')
1✔
327
        dt1 = DateTime(2000, 1, 1)
1✔
328

329
        dsec = (dt.millis() - dt1.millis()) / 1000.0
1✔
330
        ddays = math.floor((dsec / 86400.0) + 0.5)
1✔
331

332
        self.assertEqual(ddays, 3000000, ddays)
1✔
333

334
    def test_tzoffset(self):
1✔
335
        # Test time-zone given as an offset
336

337
        # GMT
338
        dt = DateTime('Tue, 10 Sep 2001 09:41:03 GMT')
1✔
339
        self.assertEqual(dt.tzoffset(), 0)
1✔
340

341
        # Timezone by name, a timezone that hasn't got daylightsaving.
342
        dt = DateTime('Tue, 2 Mar 2001 09:41:03 GMT+3')
1✔
343
        self.assertEqual(dt.tzoffset(), 10800)
1✔
344

345
        # Timezone by name, has daylightsaving but is not in effect.
346
        dt = DateTime('Tue, 21 Jan 2001 09:41:03 PST')
1✔
347
        self.assertEqual(dt.tzoffset(), -28800)
1✔
348

349
        # Timezone by name, with daylightsaving in effect
350
        dt = DateTime('Tue, 24 Aug 2001 09:41:03 PST')
1✔
351
        self.assertEqual(dt.tzoffset(), -25200)
1✔
352

353
        # A negative numerical timezone
354
        dt = DateTime('Tue, 24 Jul 2001 09:41:03 -0400')
1✔
355
        self.assertEqual(dt.tzoffset(), -14400)
1✔
356

357
        # A positive numerical timzone
358
        dt = DateTime('Tue, 6 Dec 1966 01:41:03 +0200')
1✔
359
        self.assertEqual(dt.tzoffset(), 7200)
1✔
360

361
        # A negative numerical timezone with minutes.
362
        dt = DateTime('Tue, 24 Jul 2001 09:41:03 -0637')
1✔
363
        self.assertEqual(dt.tzoffset(), -23820)
1✔
364

365
        # A positive numerical timezone with minutes.
366
        dt = DateTime('Tue, 24 Jul 2001 09:41:03 +0425')
1✔
367
        self.assertEqual(dt.tzoffset(), 15900)
1✔
368

369
    def testISO8601(self):
1✔
370
        # ISO8601 reference dates
371
        ref0 = DateTime('2002/5/2 8:00am GMT')
1✔
372
        ref1 = DateTime('2002/5/2 8:00am US/Eastern')
1✔
373
        ref2 = DateTime('2006/11/6 10:30 GMT')
1✔
374
        ref3 = DateTime('2004/06/14 14:30:15 GMT-3')
1✔
375
        ref4 = DateTime('2006/01/01 GMT')
1✔
376

377
        # Basic tests
378
        # Though this is timezone naive and according to specification should
379
        # be interpreted in the local timezone, to preserve backwards
380
        # compatibility with previously expected behaviour.
381
        isoDt = DateTime('2002-05-02T08:00:00')
1✔
382
        self.assertTrue(ref0.equalTo(isoDt))
1✔
383
        isoDt = DateTime('2002-05-02T08:00:00Z')
1✔
384
        self.assertTrue(ref0.equalTo(isoDt))
1✔
385
        isoDt = DateTime('2002-05-02T08:00:00+00:00')
1✔
386
        self.assertTrue(ref0.equalTo(isoDt))
1✔
387
        isoDt = DateTime('2002-05-02T08:00:00-04:00')
1✔
388
        self.assertTrue(ref1.equalTo(isoDt))
1✔
389
        isoDt = DateTime('2002-05-02 08:00:00-04:00')
1✔
390
        self.assertTrue(ref1.equalTo(isoDt))
1✔
391

392
        # Bug 1386: the colon in the timezone offset is optional
393
        isoDt = DateTime('2002-05-02T08:00:00-0400')
1✔
394
        self.assertTrue(ref1.equalTo(isoDt))
1✔
395

396
        # Bug 2191: date reduced formats
397
        isoDt = DateTime('2006-01-01')
1✔
398
        self.assertTrue(ref4.equalTo(isoDt))
1✔
399
        isoDt = DateTime('200601-01')
1✔
400
        self.assertTrue(ref4.equalTo(isoDt))
1✔
401
        isoDt = DateTime('20060101')
1✔
402
        self.assertTrue(ref4.equalTo(isoDt))
1✔
403
        isoDt = DateTime('2006-01')
1✔
404
        self.assertTrue(ref4.equalTo(isoDt))
1✔
405
        isoDt = DateTime('200601')
1✔
406
        self.assertTrue(ref4.equalTo(isoDt))
1✔
407
        isoDt = DateTime('2006')
1✔
408
        self.assertTrue(ref4.equalTo(isoDt))
1✔
409

410
        # Bug 2191: date/time separators are also optional
411
        isoDt = DateTime('20020502T08:00:00')
1✔
412
        self.assertTrue(ref0.equalTo(isoDt))
1✔
413
        isoDt = DateTime('2002-05-02T080000')
1✔
414
        self.assertTrue(ref0.equalTo(isoDt))
1✔
415
        isoDt = DateTime('20020502T080000')
1✔
416
        self.assertTrue(ref0.equalTo(isoDt))
1✔
417

418
        # Bug 2191: timezones with only one digit for hour
419
        isoDt = DateTime('20020502T080000+0')
1✔
420
        self.assertTrue(ref0.equalTo(isoDt))
1✔
421
        isoDt = DateTime('20020502 080000-4')
1✔
422
        self.assertTrue(ref1.equalTo(isoDt))
1✔
423
        isoDt = DateTime('20020502T080000-400')
1✔
424
        self.assertTrue(ref1.equalTo(isoDt))
1✔
425
        isoDt = DateTime('20020502T080000-4:00')
1✔
426
        self.assertTrue(ref1.equalTo(isoDt))
1✔
427

428
        # Bug 2191: optional seconds/minutes
429
        isoDt = DateTime('2002-05-02T0800')
1✔
430
        self.assertTrue(ref0.equalTo(isoDt))
1✔
431
        isoDt = DateTime('2002-05-02T08')
1✔
432
        self.assertTrue(ref0.equalTo(isoDt))
1✔
433

434
        # Bug 2191: week format
435
        isoDt = DateTime('2002-W18-4T0800')
1✔
436
        self.assertTrue(ref0.equalTo(isoDt))
1✔
437
        isoDt = DateTime('2002-W184T0800')
1✔
438
        self.assertTrue(ref0.equalTo(isoDt))
1✔
439
        isoDt = DateTime('2002W18-4T0800')
1✔
440
        self.assertTrue(ref0.equalTo(isoDt))
1✔
441
        isoDt = DateTime('2002W184T08')
1✔
442
        self.assertTrue(ref0.equalTo(isoDt))
1✔
443
        isoDt = DateTime('2004-W25-1T14:30:15-03:00')
1✔
444
        self.assertTrue(ref3.equalTo(isoDt))
1✔
445
        isoDt = DateTime('2004-W25T14:30:15-03:00')
1✔
446
        self.assertTrue(ref3.equalTo(isoDt))
1✔
447

448
        # Bug 2191: day of year format
449
        isoDt = DateTime('2002-122T0800')
1✔
450
        self.assertTrue(ref0.equalTo(isoDt))
1✔
451
        isoDt = DateTime('2002122T0800')
1✔
452
        self.assertTrue(ref0.equalTo(isoDt))
1✔
453

454
        # Bug 2191: hours/minutes fractions
455
        isoDt = DateTime('2006-11-06T10.5')
1✔
456
        self.assertTrue(ref2.equalTo(isoDt))
1✔
457
        isoDt = DateTime('2006-11-06T10,5')
1✔
458
        self.assertTrue(ref2.equalTo(isoDt))
1✔
459
        isoDt = DateTime('20040614T1430.25-3')
1✔
460
        self.assertTrue(ref3.equalTo(isoDt))
1✔
461
        isoDt = DateTime('2004-06-14T1430,25-3')
1✔
462
        self.assertTrue(ref3.equalTo(isoDt))
1✔
463
        isoDt = DateTime('2004-06-14T14:30.25-3')
1✔
464
        self.assertTrue(ref3.equalTo(isoDt))
1✔
465
        isoDt = DateTime('20040614T14:30,25-3')
1✔
466
        self.assertTrue(ref3.equalTo(isoDt))
1✔
467

468
        # ISO8601 standard format
469
        iso8601_string = '2002-05-02T08:00:00-04:00'
1✔
470
        iso8601DT = DateTime(iso8601_string)
1✔
471
        self.assertEqual(iso8601_string, iso8601DT.ISO8601())
1✔
472

473
        # ISO format with no timezone
474
        isoDt = DateTime('2006-01-01 00:00:00')
1✔
475
        self.assertTrue(ref4.equalTo(isoDt))
1✔
476

477
    def testJulianWeek(self):
1✔
478
        # Check JulianDayWeek function
479
        fn = os.path.join(DATADIR, 'julian_testdata.txt')
1✔
480
        with open(fn, 'r') as fd:
1✔
481
            lines = fd.readlines()
1✔
482
        for line in lines:
1✔
483
            d = DateTime(line[:10])
1✔
484
            result_from_mx = tuple(map(int, line[12:-2].split(',')))
1✔
485
            self.assertEqual(result_from_mx[1], d.week())
1✔
486

487
    def testCopyConstructor(self):
1✔
488
        d = DateTime('2004/04/04')
1✔
489
        self.assertEqual(DateTime(d), d)
1✔
490
        self.assertEqual(str(DateTime(d)), str(d))
1✔
491
        d2 = DateTime('1999/04/12 01:00:00')
1✔
492
        self.assertEqual(DateTime(d2), d2)
1✔
493
        self.assertEqual(str(DateTime(d2)), str(d2))
1✔
494

495
    def testCopyConstructorPreservesTimezone(self):
1✔
496
        # test for https://bugs.launchpad.net/zope2/+bug/200007
497
        # This always worked in the local timezone, so we need at least
498
        # two tests with different zones to be sure at least one of them
499
        # is not local.
500
        d = DateTime('2004/04/04')
1✔
501
        self.assertEqual(DateTime(d).timezone(), d.timezone())
1✔
502
        d2 = DateTime('2008/04/25 12:00:00 EST')
1✔
503
        self.assertEqual(DateTime(d2).timezone(), d2.timezone())
1✔
504
        self.assertEqual(str(DateTime(d2)), str(d2))
1✔
505
        d3 = DateTime('2008/04/25 12:00:00 PST')
1✔
506
        self.assertEqual(DateTime(d3).timezone(), d3.timezone())
1✔
507
        self.assertEqual(str(DateTime(d3)), str(d3))
1✔
508

509
    def testRFC822(self):
1✔
510
        # rfc822 conversion
511
        dt = DateTime('2002-05-02T08:00:00+00:00')
1✔
512
        self.assertEqual(dt.rfc822(), 'Thu, 02 May 2002 08:00:00 +0000')
1✔
513

514
        dt = DateTime('2002-05-02T08:00:00+02:00')
1✔
515
        self.assertEqual(dt.rfc822(), 'Thu, 02 May 2002 08:00:00 +0200')
1✔
516

517
        dt = DateTime('2002-05-02T08:00:00-02:00')
1✔
518
        self.assertEqual(dt.rfc822(), 'Thu, 02 May 2002 08:00:00 -0200')
1✔
519

520
        # Checking that conversion from local time is working.
521
        dt = DateTime()
1✔
522
        dts = dt.rfc822().split(' ')
1✔
523
        times = dts[4].split(':')
1✔
524
        _isDST = time.localtime(time.time())[8]
1✔
525
        if _isDST:
1!
526
            offset = time.altzone
×
527
        else:
528
            offset = time.timezone
1✔
529
        self.assertEqual(dts[0], dt.aDay() + ',')
1✔
530
        self.assertEqual(int(dts[1]), dt.day())
1✔
531
        self.assertEqual(dts[2], dt.aMonth())
1✔
532
        self.assertEqual(int(dts[3]), dt.year())
1✔
533
        self.assertEqual(int(times[0]), dt.h_24())
1✔
534
        self.assertEqual(int(times[1]), dt.minute())
1✔
535
        self.assertEqual(int(times[2]), int(dt.second()))
1✔
536
        self.assertEqual(dts[5], "%+03d%02d" % divmod((-offset / 60), 60))
1✔
537

538
    def testInternationalDateformat(self):
1✔
539
        for year in (1990, 2001, 2020):
1✔
540
            for month in (1, 12):
1✔
541
                for day in (1, 12, 28, 31):
1✔
542
                    try:
1✔
543
                        d_us = DateTime("%d/%d/%d" % (year, month, day))
1✔
544
                    except Exception:
×
545
                        continue
×
546

547
                    d_int = DateTime("%d.%d.%d" % (day, month, year),
1✔
548
                                     datefmt="international")
549
                    self.assertEqual(d_us, d_int)
1✔
550

551
                    d_int = DateTime("%d/%d/%d" % (day, month, year),
1✔
552
                                     datefmt="international")
553
                    self.assertEqual(d_us, d_int)
1✔
554

555
    def test_intl_format_hyphen(self):
1✔
556
        d_jan = DateTime('2011-01-11 GMT')
1✔
557
        d_nov = DateTime('2011-11-01 GMT')
1✔
558
        d_us = DateTime('11-01-2011 GMT')
1✔
559
        d_int = DateTime('11-01-2011 GMT', datefmt="international")
1✔
560
        self.assertNotEqual(d_us, d_int)
1✔
561
        self.assertEqual(d_us, d_nov)
1✔
562
        self.assertEqual(d_int, d_jan)
1✔
563

564
    def test_calcTimezoneName(self):
1✔
565
        from DateTime.interfaces import TimeError
1✔
566
        timezone_dependent_epoch = 2177452800
1✔
567
        try:
1✔
568
            DateTime()._calcTimezoneName(timezone_dependent_epoch, 0)
1✔
569
        except TimeError:
×
570
            self.fail('Zope Collector issue #484 (negative time bug): '
571
                      'TimeError raised')
572

573
    def testStrftimeTZhandling(self):
1✔
574
        # strftime timezone testing
575
        # This is a test for collector issue #1127
576
        format = '%Y-%m-%d %H:%M %Z'
1✔
577
        dt = DateTime('Wed, 19 Nov 2003 18:32:07 -0215')
1✔
578
        dt_string = dt.strftime(format)
1✔
579
        dt_local = dt.toZone(_findLocalTimeZoneName(0))
1✔
580
        dt_localstring = dt_local.strftime(format)
1✔
581
        self.assertEqual(dt_string, dt_localstring)
1✔
582

583
    def testStrftimeFarDates(self):
1✔
584
        # Checks strftime in dates <= 1900 or >= 2038
585
        dt = DateTime('1900/01/30')
1✔
586
        self.assertEqual(dt.strftime('%d/%m/%Y'), '30/01/1900')
1✔
587
        dt = DateTime('2040/01/30')
1✔
588
        self.assertEqual(dt.strftime('%d/%m/%Y'), '30/01/2040')
1✔
589

590
    def testZoneInFarDates(self):
1✔
591
        # Checks time zone in dates <= 1900 or >= 2038
592
        dt1 = DateTime('2040/01/30 14:33 GMT+1')
1✔
593
        dt2 = DateTime('2040/01/30 11:33 GMT-2')
1✔
594
        self.assertEqual(dt1.strftime('%d/%m/%Y %H:%M'),
1✔
595
                         dt2.strftime('%d/%m/%Y %H:%M'))
596

597
    @unittest.skipIf(
1✔
598
        IS_PYPY,
599
        "Using Non-Ascii characters for strftime doesn't work in PyPy"
600
        "https://bitbucket.org/pypy/pypy/issues/2161/pypy3-strftime-does-not-accept-unicode"  # noqa: E501 line too long
601
    )
602
    def testStrftimeUnicode(self):
1✔
603
        dt = DateTime('2002-05-02T08:00:00+00:00')
1✔
604
        uchar = b'\xc3\xa0'.decode('utf-8')
1✔
605
        ok = dt.strftime('Le %d/%m/%Y a %Hh%M').replace('a', uchar)
1✔
606
        ustr = b'Le %d/%m/%Y \xc3\xa0 %Hh%M'.decode('utf-8')
1✔
607
        self.assertEqual(dt.strftime(ustr), ok)
1✔
608

609
    def testTimezoneNaiveHandling(self):
1✔
610
        # checks that we assign timezone naivity correctly
611
        dt = DateTime('2007-10-04T08:00:00+00:00')
1✔
612
        self.assertFalse(dt.timezoneNaive(),
1✔
613
                         'error with naivity handling in __parse_iso8601')
614
        dt = DateTime('2007-10-04T08:00:00Z')
1✔
615
        self.assertFalse(dt.timezoneNaive(),
1✔
616
                         'error with naivity handling in __parse_iso8601')
617
        dt = DateTime('2007-10-04T08:00:00')
1✔
618
        self.assertTrue(dt.timezoneNaive(),
1✔
619
                        'error with naivity handling in __parse_iso8601')
620
        dt = DateTime('2007/10/04 15:12:33.487618 GMT+1')
1✔
621
        self.assertFalse(dt.timezoneNaive(),
1✔
622
                         'error with naivity handling in _parse')
623
        dt = DateTime('2007/10/04 15:12:33.487618')
1✔
624
        self.assertTrue(dt.timezoneNaive(),
1✔
625
                        'error with naivity handling in _parse')
626
        dt = DateTime()
1✔
627
        self.assertFalse(dt.timezoneNaive(),
1✔
628
                         'error with naivity for current time')
629
        s = '2007-10-04T08:00:00'
1✔
630
        dt = DateTime(s)
1✔
631
        self.assertEqual(s, dt.ISO8601())
1✔
632
        s = '2007-10-04T08:00:00+00:00'
1✔
633
        dt = DateTime(s)
1✔
634
        self.assertEqual(s, dt.ISO8601())
1✔
635

636
    def testConversions(self):
1✔
637
        sdt0 = datetime.now()  # this is a timezone naive datetime
1✔
638
        dt0 = DateTime(sdt0)
1✔
639
        self.assertTrue(dt0.timezoneNaive(), (sdt0, dt0))
1✔
640
        sdt1 = datetime(2007, 10, 4, 18, 14, 42, 580, pytz.utc)
1✔
641
        dt1 = DateTime(sdt1)
1✔
642
        self.assertFalse(dt1.timezoneNaive(), (sdt1, dt1))
1✔
643

644
        # convert back
645
        sdt2 = dt0.asdatetime()
1✔
646
        self.assertEqual(sdt0, sdt2)
1✔
647
        sdt3 = dt1.utcdatetime()  # this returns a timezone naive datetime
1✔
648
        self.assertEqual(sdt1.hour, sdt3.hour)
1✔
649

650
        dt4 = DateTime('2007-10-04T10:00:00+05:00')
1✔
651
        sdt4 = datetime(2007, 10, 4, 5, 0)
1✔
652
        self.assertEqual(dt4.utcdatetime(), sdt4)
1✔
653
        self.assertEqual(dt4.asdatetime(), sdt4.replace(tzinfo=pytz.utc))
1✔
654

655
        dt5 = DateTime('2007-10-23 10:00:00 US/Eastern')
1✔
656
        tz = pytz.timezone('US/Eastern')
1✔
657
        sdt5 = datetime(2007, 10, 23, 10, 0, tzinfo=tz)
1✔
658
        dt6 = DateTime(sdt5)
1✔
659
        self.assertEqual(dt5.asdatetime(), sdt5)
1✔
660
        self.assertEqual(dt6.asdatetime(), sdt5)
1✔
661
        self.assertEqual(dt5, dt6)
1✔
662
        self.assertEqual(dt5.asdatetime().tzinfo, tz)
1✔
663
        self.assertEqual(dt6.asdatetime().tzinfo, tz)
1✔
664

665
    def testBasicTZ(self):
1✔
666
        # psycopg2 supplies it's own tzinfo instances, with no `zone` attribute
667
        tz = FixedOffset(60, 'GMT+1')
1✔
668
        dt1 = datetime(2008, 8, 5, 12, 0, tzinfo=tz)
1✔
669
        DT = DateTime(dt1)
1✔
670
        dt2 = DT.asdatetime()
1✔
671
        offset1 = dt1.tzinfo.utcoffset(dt1)
1✔
672
        offset2 = dt2.tzinfo.utcoffset(dt2)
1✔
673
        self.assertEqual(offset1, offset2)
1✔
674

675
    def testEDTTimezone(self):
1✔
676
        # should be able to parse EDT timezones:  see lp:599856.
677
        dt = DateTime("Mon, 28 Jun 2010 10:12:25 EDT")
1✔
678
        self.assertEqual(dt.Day(), 'Monday')
1✔
679
        self.assertEqual(dt.day(), 28)
1✔
680
        self.assertEqual(dt.Month(), 'June')
1✔
681
        self.assertEqual(dt.timezone(), 'GMT-4')
1✔
682

683
    def testParseISO8601(self):
1✔
684
        parsed = DateTime()._parse_iso8601('2010-10-10')
1✔
685
        self.assertEqual(parsed, (2010, 10, 10, 0, 0, 0, 'GMT+0000'))
1✔
686

687
    def test_interface(self):
1✔
688
        from DateTime.interfaces import IDateTime
1✔
689
        self.assertTrue(IDateTime.providedBy(DateTime()))
1✔
690

691
    def test_security(self):
1✔
692
        dt = DateTime()
1✔
693
        self.assertEqual(dt.__roles__, None)
1✔
694
        self.assertEqual(dt.__allow_access_to_unprotected_subobjects__, 1)
1✔
695

696
    @unittest.skipUnless(PY3K, 'format method is Python 3 only')
1✔
697
    def test_format(self):
1✔
698
        dt = DateTime(1968, 3, 10, 23, 45, 0, 'Europe/Vienna')
1✔
699
        fmt = '%d.%m.%Y %H:%M'
1✔
700
        result = dt.strftime(fmt)
1✔
701
        unformatted_result = '1968/03/10 23:45:00 Europe/Vienna'
1✔
702
        self.assertEqual(result, '{:%d.%m.%Y %H:%M}'.format(dt))
1✔
703
        self.assertEqual(unformatted_result, '{:}'.format(dt))
1✔
704
        self.assertEqual(unformatted_result, '{}'.format(dt))
1✔
705
        eval("self.assertEqual(result, f'{dt:{fmt}}')")
1✔
706
        eval("self.assertEqual(unformatted_result ,f'{dt:}')")
1✔
707
        eval("self.assertEqual(unformatted_result, f'{dt}')")
1✔
708

709

710
def test_suite():
1✔
711
    import doctest
1✔
712
    return unittest.TestSuite([
1✔
713
        unittest.makeSuite(DateTimeTests),
714
        doctest.DocFileSuite('DateTime.txt', package='DateTime'),
715
        doctest.DocFileSuite('pytz.txt', package='DateTime'),
716
    ])
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc