Skip to content

Commit 8d7a40c

Browse files
committed
[GR-68653] Fix setting time.tzname when the timezone has no DST
PullRequest: graalpython/3950
2 parents e42e0cd + 3b13d07 commit 8d7a40c

File tree

5 files changed

+57
-21
lines changed

5 files changed

+57
-21
lines changed

.github/workflows/downstream-tests.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ jobs:
1414
- virtualenv
1515
- pyo3
1616
- pydantic-core
17+
- jiter
1718
os:
1819
- id: ubuntu-latest
1920
platform: linux
@@ -36,7 +37,7 @@ jobs:
3637
run: brew install cmake
3738

3839
- name: Install Rust toolchain
39-
if: ${{ matrix.name == 'pyo3' || matrix.name == 'pydantic-core' }}
40+
if: ${{ matrix.name == 'pyo3' || matrix.name == 'pydantic-core' || matrix.name == 'jiter' }}
4041
run: |
4142
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
4243
echo "${HOME}/.cargo/bin" >> $GITHUB_PATH

ci.jsonnet

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@
502502
) + [
503503
{
504504
name: "graalpy-website-build",
505-
targets: ["gate"],
505+
targets: ["tier1"],
506506
guard: {
507507
includes: ["docs/user/**", "docs/site/**"],
508508
},

graalpython/com.oracle.graal.python.test/src/tests/test_time.py

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -36,10 +36,14 @@
3636
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3737
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3838
# SOFTWARE.
39-
40-
import time
4139
import calendar
40+
import os
41+
import subprocess
42+
import sys
43+
import time
4244
import unittest
45+
from textwrap import dedent
46+
4347

4448
def test_sleep():
4549
start = time.time()
@@ -72,19 +76,19 @@ def test_new_struct_time(self):
7276
self.assertEqual(t.tm_mday, 26)
7377
self.assertEqual(t[2], 26)
7478
self.assertEqual(t.tm_zone, None)
75-
79+
7680
self.assertRaises(TypeError, time.struct_time, (2018, 11, 26, 17, 34, 12, 0, 340))
7781
self.assertRaises(TypeError, time.struct_time, (2018, 11, 26, 17, 34, 12, 0, 340, 9, 10, 11, 12))
7882

7983
def test_from_times(self):
8084
gt = time.gmtime()
8185
self.assertNotEqual(gt.tm_zone, None)
8286
self.assertNotEqual(gt.tm_gmtoff, None)
83-
87+
8488
lt = time.localtime()
8589
self.assertNotEqual(lt.tm_zone, None)
8690
self.assertNotEqual(lt.tm_gmtoff, None)
87-
91+
8892
def test_destructuring_assignment(self):
8993
t = time.struct_time((1,2,3,4,5,6,7,8,9))
9094
y,m,d,h,mi,s,wd,yd,dst = t
@@ -93,7 +97,7 @@ def test_destructuring_assignment(self):
9397
self.assertEqual(dst, 9)
9498
self.assertEqual(t.tm_zone, None)
9599
self.assertEqual(t.tm_gmtoff, None)
96-
100+
97101
t = time.struct_time((11,12,13,14,15,16,17,18,19,20, 21))
98102
y,m,d,h,mi,s,wd,yd,dst = t
99103
self.assertEqual(y, 11)
@@ -234,7 +238,7 @@ def test_Yeary(self):
234238
self.check_format("%y", (2018, 11, 28, 10, 0, 0, -1, 1, 0), '18')
235239
self.check_format("%y", (18, 11, 28, 10, 0, 0, 0, 1, 0), '18')
236240
self.check_format("%y", (0, 11, 25, 11, 12, 2, 3, 1, 0), '00')
237-
# This is failing on CPython, which return '35'
241+
# This is failing on CPython, which return '35'
238242
#self.check_format("%y", (-365, 11, 24, 23, 20, 61, 6, 1, 0), '65')
239243
self.check_format("%y", (17829, 11, 24, 23, 20, 61, 7, 1, 0), '29')
240244

@@ -280,3 +284,28 @@ def test_padding(self):
280284
self.check_format("%Y-%b-%d-%j", (2018, 8, 8, 15, 24, 10, 3, 55, 0), '2018-Aug-08-055')
281285
self.check_format("%Y-%b-%-d-%-j", (2018, 8, 8, 15, 24, 10, 3, 5, 0), '2018-Aug-8-5')
282286
self.check_format("%Y-%b-%-d-%-j", (2018, 8, 8, 15, 24, 10, 3, 55, 0), '2018-Aug-8-55')
287+
288+
@unittest.skipIf(sys.platform == 'win32', "Cannot change timezone per-process on Windows")
289+
def test_default_tz_dst_no_dst(self):
290+
env = os.environ.copy()
291+
testdate = '1994-11-15 12:45:26'
292+
for tz, expected in [
293+
('UTC', f"tzname=('UTC', 'UTC'), timezone=0, altzone=0, daylight=0, testdate={testdate}"),
294+
('Europe/Prague', f"tzname=('CET', 'CEST'), timezone=-3600, altzone=-7200, daylight=1, testdate={testdate}"),
295+
('Australia/Sydney', f"tzname=('AEST', 'AEDT'), timezone=-36000, altzone=-39600, daylight=1, testdate={testdate}"),
296+
]:
297+
env['TZ'] = tz
298+
env['LC_ALL'] = 'C'
299+
script = dedent('''\
300+
from time import *
301+
from datetime import datetime
302+
# Regression test for issue #532
303+
testdate = datetime.strptime('Tue, 15 Nov 1994 12:45:26 GMT', '%a, %d %b %Y %H:%M:%S %Z')
304+
print(f'{tzname=}, {timezone=}, {altzone=}, {daylight=}, {testdate=!s}')
305+
''')
306+
out = subprocess.check_output(
307+
[sys.executable, '-c', script],
308+
env=env,
309+
text=True,
310+
).strip()
311+
self.assertEqual(expected, out)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TimeModuleBuiltins.java

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -174,17 +174,10 @@ public void postInitialize(Python3Core core) {
174174
TruffleString noDaylightSavingZone = toTruffleStringUncached(defaultTimeZone.getDisplayName(false, TimeZone.SHORT));
175175
TruffleString daylightSavingZone = toTruffleStringUncached(defaultTimeZone.getDisplayName(true, TimeZone.SHORT));
176176

177-
boolean hasDaylightSaving = !noDaylightSavingZone.equalsUncached(daylightSavingZone, TS_ENCODING);
178-
if (hasDaylightSaving) {
179-
timeModule.setAttribute(T_TZNAME, PFactory.createTuple(core.getLanguage(), new Object[]{noDaylightSavingZone, daylightSavingZone}));
180-
} else {
181-
timeModule.setAttribute(T_TZNAME, PFactory.createTuple(core.getLanguage(), new Object[]{noDaylightSavingZone}));
182-
}
183-
184-
timeModule.setAttribute(T_DAYLIGHT, PInt.intValue(hasDaylightSaving));
185-
int rawOffsetSeconds = defaultTimeZone.getRawOffset() / -1000;
186-
timeModule.setAttribute(T_TIMEZONE, rawOffsetSeconds);
187-
timeModule.setAttribute(T_ALTZONE, rawOffsetSeconds - 3600);
177+
timeModule.setAttribute(T_TZNAME, PFactory.createTuple(core.getLanguage(), new Object[]{noDaylightSavingZone, daylightSavingZone}));
178+
timeModule.setAttribute(T_DAYLIGHT, PInt.intValue(defaultTimeZone.getDSTSavings() != 0));
179+
timeModule.setAttribute(T_TIMEZONE, defaultTimeZone.getRawOffset() / -1000);
180+
timeModule.setAttribute(T_ALTZONE, (defaultTimeZone.getRawOffset() + defaultTimeZone.getDSTSavings()) / -1000);
188181

189182
// register_interop_behavior() for time.struct_time
190183
AbstractImportNode.importModule(T_POLYGLOT_TIME);

mx.graalpython/downstream_tests.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,19 @@ def downstream_test_pydantic_core(graalpy, testdir):
158158
run(['uv', 'run', 'pytest', '-v', '--tb=short'], cwd=src)
159159

160160

161+
@downstream_test('jiter')
162+
def downstream_test_jiter(graalpy, testdir):
163+
run(['git', 'clone', 'https://github.com/pydantic/jiter.git', '-b', 'main'], cwd=testdir)
164+
src = testdir / 'jiter'
165+
venv = src / 'venv'
166+
run([graalpy, '-m', 'venv', str(venv)])
167+
run_in_venv(venv, ['pip', 'install', '-r', 'crates/jiter-python/tests/requirements.txt'], cwd=src)
168+
run_in_venv(venv, ['pip', 'install', '-e', 'crates/jiter-python',
169+
'--config-settings=build-args=--profile dev'], cwd=src)
170+
run_in_venv(venv, ['pytest', '-v', '--tb=short', 'crates/jiter-python/tests'], cwd=src)
171+
run_in_venv(venv, ['python', 'crates/jiter-python/bench.py', 'jiter', 'jiter-cache', '--fast'], cwd=src)
172+
173+
161174
def run_downstream_test(python, project):
162175
testdir = Path('upstream-tests').absolute()
163176
shutil.rmtree(testdir, ignore_errors=True)

0 commit comments

Comments
 (0)