summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/datetime.py45
-rw-r--r--Lib/test/datetimetester.py21
2 files changed, 35 insertions, 31 deletions
diff --git a/Lib/datetime.py b/Lib/datetime.py
index 00ded32..007114a 100644
--- a/Lib/datetime.py
+++ b/Lib/datetime.py
@@ -179,7 +179,7 @@ def _format_time(hh, mm, ss, us, timespec='auto'):
else:
return fmt.format(hh, mm, ss, us)
-def _format_offset(off):
+def _format_offset(off, sep=':'):
s = ''
if off is not None:
if off.days < 0:
@@ -189,9 +189,9 @@ def _format_offset(off):
sign = "+"
hh, mm = divmod(off, timedelta(hours=1))
mm, ss = divmod(mm, timedelta(minutes=1))
- s += "%s%02d:%02d" % (sign, hh, mm)
+ s += "%s%02d%s%02d" % (sign, hh, sep, mm)
if ss or ss.microseconds:
- s += ":%02d" % ss.seconds
+ s += "%s%02d" % (sep, ss.seconds)
if ss.microseconds:
s += '.%06d' % ss.microseconds
@@ -202,9 +202,10 @@ def _wrap_strftime(object, format, timetuple):
# Don't call utcoffset() or tzname() unless actually needed.
freplace = None # the string to use for %f
zreplace = None # the string to use for %z
+ colonzreplace = None # the string to use for %:z
Zreplace = None # the string to use for %Z
- # Scan format for %z and %Z escapes, replacing as needed.
+ # Scan format for %z, %:z and %Z escapes, replacing as needed.
newformat = []
push = newformat.append
i, n = 0, len(format)
@@ -222,26 +223,28 @@ def _wrap_strftime(object, format, timetuple):
newformat.append(freplace)
elif ch == 'z':
if zreplace is None:
- zreplace = ""
if hasattr(object, "utcoffset"):
- offset = object.utcoffset()
- if offset is not None:
- sign = '+'
- if offset.days < 0:
- offset = -offset
- sign = '-'
- h, rest = divmod(offset, timedelta(hours=1))
- m, rest = divmod(rest, timedelta(minutes=1))
- s = rest.seconds
- u = offset.microseconds
- if u:
- zreplace = '%c%02d%02d%02d.%06d' % (sign, h, m, s, u)
- elif s:
- zreplace = '%c%02d%02d%02d' % (sign, h, m, s)
- else:
- zreplace = '%c%02d%02d' % (sign, h, m)
+ zreplace = _format_offset(object.utcoffset(), sep="")
+ else:
+ zreplace = ""
assert '%' not in zreplace
newformat.append(zreplace)
+ elif ch == ':':
+ if i < n:
+ ch2 = format[i]
+ i += 1
+ if ch2 == 'z':
+ if colonzreplace is None:
+ if hasattr(object, "utcoffset"):
+ colonzreplace = _format_offset(object.utcoffset(), sep=":")
+ else:
+ colonzreplace = ""
+ assert '%' not in colonzreplace
+ newformat.append(colonzreplace)
+ else:
+ push('%')
+ push(ch)
+ push(ch2)
elif ch == 'Z':
if Zreplace is None:
Zreplace = ""
diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py
index 7e7f4f3..bba9669 100644
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -1463,8 +1463,8 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase):
# test that unicode input is allowed (issue 2782)
self.assertEqual(t.strftime("%m"), "03")
- # A naive object replaces %z and %Z w/ empty strings.
- self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''")
+ # A naive object replaces %z, %:z and %Z w/ empty strings.
+ self.assertEqual(t.strftime("'%z' '%:z' '%Z'"), "'' '' ''")
#make sure that invalid format specifiers are handled correctly
#self.assertRaises(ValueError, t.strftime, "%e")
@@ -1528,7 +1528,7 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase):
for fmt in ["m:%m d:%d y:%y",
"m:%m d:%d y:%y H:%H M:%M S:%S",
- "%z %Z",
+ "%z %:z %Z",
]:
self.assertEqual(dt.__format__(fmt), dt.strftime(fmt))
self.assertEqual(a.__format__(fmt), dt.strftime(fmt))
@@ -2134,7 +2134,7 @@ class TestDateTime(TestDate):
for fmt in ["m:%m d:%d y:%y",
"m:%m d:%d y:%y H:%H M:%M S:%S",
- "%z %Z",
+ "%z %:z %Z",
]:
self.assertEqual(dt.__format__(fmt), dt.strftime(fmt))
self.assertEqual(a.__format__(fmt), dt.strftime(fmt))
@@ -2777,6 +2777,7 @@ class TestDateTime(TestDate):
tz = timezone(-timedelta(hours=2, seconds=s, microseconds=us))
t = t.replace(tzinfo=tz)
self.assertEqual(t.strftime("%z"), "-0200" + z)
+ self.assertEqual(t.strftime("%:z"), "-02:00:" + z)
# bpo-34482: Check that surrogates don't cause a crash.
try:
@@ -3515,8 +3516,8 @@ class TestTime(HarmlessMixedComparison, unittest.TestCase):
def test_strftime(self):
t = self.theclass(1, 2, 3, 4)
self.assertEqual(t.strftime('%H %M %S %f'), "01 02 03 000004")
- # A naive object replaces %z and %Z with empty strings.
- self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''")
+ # A naive object replaces %z, %:z and %Z with empty strings.
+ self.assertEqual(t.strftime("'%z' '%:z' '%Z'"), "'' '' ''")
# bpo-34482: Check that surrogates don't cause a crash.
try:
@@ -3934,10 +3935,10 @@ class TestTimeTZ(TestTime, TZInfoBase, unittest.TestCase):
self.assertEqual(repr(t4), d + "(0, 0, 0, 40)")
self.assertEqual(repr(t5), d + "(0, 0, 0, 40, tzinfo=utc)")
- self.assertEqual(t1.strftime("%H:%M:%S %%Z=%Z %%z=%z"),
- "07:47:00 %Z=EST %z=-0500")
- self.assertEqual(t2.strftime("%H:%M:%S %Z %z"), "12:47:00 UTC +0000")
- self.assertEqual(t3.strftime("%H:%M:%S %Z %z"), "13:47:00 MET +0100")
+ self.assertEqual(t1.strftime("%H:%M:%S %%Z=%Z %%z=%z %%:z=%:z"),
+ "07:47:00 %Z=EST %z=-0500 %:z=-05:00")
+ self.assertEqual(t2.strftime("%H:%M:%S %Z %z %:z"), "12:47:00 UTC +0000 +00:00")
+ self.assertEqual(t3.strftime("%H:%M:%S %Z %z %:z"), "13:47:00 MET +0100 +01:00")
yuck = FixedOffset(-1439, "%z %Z %%z%%Z")
t1 = time(23, 59, tzinfo=yuck)