Skip to content

Commit 3d5f34f

Browse files
committed
Store the current timezone in a hidden field
1 parent 6ae1101 commit 3d5f34f

File tree

1 file changed

+54
-36
lines changed

1 file changed

+54
-36
lines changed

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

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,12 @@
7171
import com.oracle.graal.python.nodes.ErrorMessages;
7272
import com.oracle.graal.python.nodes.PNodeWithContext;
7373
import com.oracle.graal.python.nodes.PRaiseNode;
74+
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromDynamicObjectNode;
7475
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
7576
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
77+
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
7678
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryClinicBuiltinNode;
79+
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryClinicBuiltinNode;
7780
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
7881
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryClinicBuiltinNode;
7982
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
@@ -105,7 +108,9 @@
105108
public final class TimeModuleBuiltins extends PythonBuiltins {
106109
private static final int DELAY_NANOS = 10;
107110
private static final String CTIME_FORMAT = "%s %s %2d %02d:%02d:%02d %d";
111+
private static final ZoneId GMT = ZoneId.of("GMT");
108112

113+
private static final HiddenKey CURRENT_ZONE_ID = new HiddenKey("currentZoneID");
109114
private static final HiddenKey TIME_SLEPT = new HiddenKey("timeSlept");
110115

111116
private static final StructSequence.BuiltinTypeDescriptor STRUCT_TIME_DESC = new StructSequence.BuiltinTypeDescriptor(
@@ -147,7 +152,11 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
147152
@Override
148153
public void initialize(Python3Core core) {
149154
super.initialize(core);
150-
TimeZone defaultTimeZone = TimeZone.getTimeZone(core.getContext().getEnv().getTimeZone());
155+
// Should we read TZ env variable?
156+
ZoneId defaultZoneId = core.getContext().getEnv().getTimeZone();
157+
core.lookupBuiltinModule("time").setAttribute(CURRENT_ZONE_ID, defaultZoneId);
158+
159+
TimeZone defaultTimeZone = TimeZone.getTimeZone(defaultZoneId);
151160
String noDaylightSavingZone = defaultTimeZone.getDisplayName(false, TimeZone.SHORT);
152161
String daylightSavingZone = defaultTimeZone.getDisplayName(true, TimeZone.SHORT);
153162

@@ -182,10 +191,9 @@ public static double timeSeconds() {
182191
private static final int TM_ISDST = 8; /* daylight saving time */
183192

184193
@TruffleBoundary
185-
private static Object[] getTimeStruct(PythonContext context, long seconds, boolean local) {
194+
private static Object[] getTimeStruct(ZoneId zone, long seconds) {
186195
Object[] timeStruct = new Object[11];
187196
Instant instant = Instant.ofEpochSecond(seconds);
188-
ZoneId zone = (local) ? context.getEnv().getTimeZone() : ZoneId.of("GMT");
189197
ZonedDateTime zonedDateTime = LocalDateTime.ofInstant(instant, zone).atZone(zone);
190198
timeStruct[TM_YEAR] = zonedDateTime.getYear();
191199
timeStruct[TM_MON] = zonedDateTime.getMonth().ordinal() + 1; /* Want January == 1 */
@@ -204,10 +212,9 @@ private static Object[] getTimeStruct(PythonContext context, long seconds, boole
204212
}
205213

206214
@TruffleBoundary
207-
private static int[] getIntLocalTimeStruct(PythonContext context, long seconds) {
215+
private static int[] getIntLocalTimeStruct(ZoneId zone, long seconds) {
208216
int[] timeStruct = new int[9];
209217
Instant instant = Instant.ofEpochSecond(seconds);
210-
ZoneId zone = context.getEnv().getTimeZone();
211218
ZonedDateTime zonedDateTime = LocalDateTime.ofInstant(instant, zone).atZone(zone);
212219
timeStruct[TM_YEAR] = zonedDateTime.getYear();
213220
timeStruct[TM_MON] = zonedDateTime.getMonth().ordinal() + 1; /* Want January == 1 */
@@ -285,20 +292,22 @@ public abstract static class PythonGMTimeNode extends PythonBuiltinNode {
285292
@Specialization
286293
public PTuple gmtime(VirtualFrame frame, Object seconds,
287294
@Cached ToLongTime toLongTime) {
288-
return factory().createStructSeq(STRUCT_TIME_DESC, getTimeStruct(PythonContext.get(this), toLongTime.execute(frame, seconds), false));
295+
return factory().createStructSeq(STRUCT_TIME_DESC, getTimeStruct(GMT, toLongTime.execute(frame, seconds)));
289296
}
290297
}
291298

292299
// time.localtime([seconds])
293-
@Builtin(name = "localtime", maxNumOfPositionalArgs = 1)
300+
@Builtin(name = "localtime", maxNumOfPositionalArgs = 2, declaresExplicitSelf = true)
294301
@GenerateNodeFactory
295302
@TypeSystemReference(PythonArithmeticTypes.class)
296-
public abstract static class PythonLocalTimeNode extends PythonBuiltinNode {
303+
public abstract static class PythonLocalTimeNode extends PythonBinaryBuiltinNode {
297304

298305
@Specialization
299-
public PTuple localtime(VirtualFrame frame, Object seconds,
306+
public PTuple localtime(VirtualFrame frame, PythonModule module, Object seconds,
307+
@Cached ReadAttributeFromDynamicObjectNode readZoneId,
300308
@Cached ToLongTime toLongTime) {
301-
return factory().createStructSeq(STRUCT_TIME_DESC, getTimeStruct(PythonContext.get(this), toLongTime.execute(frame, seconds), true));
309+
ZoneId zoneId = (ZoneId) readZoneId.execute(module, CURRENT_ZONE_ID);
310+
return factory().createStructSeq(STRUCT_TIME_DESC, getTimeStruct(zoneId, toLongTime.execute(frame, seconds)));
302311
}
303312
}
304313

@@ -551,10 +560,10 @@ public static SleepNode create() {
551560
}
552561

553562
// time.strftime(format[, t])
554-
@Builtin(name = "strftime", minNumOfPositionalArgs = 1, parameterNames = {"format", "time"})
563+
@Builtin(name = "strftime", minNumOfPositionalArgs = 2, declaresExplicitSelf = true, parameterNames = {"$self", "format", "time"})
555564
@ArgumentClinic(name = "format", conversion = ArgumentClinic.ClinicConversion.String)
556565
@GenerateNodeFactory
557-
public abstract static class StrfTimeNode extends PythonBinaryClinicBuiltinNode {
566+
public abstract static class StrfTimeNode extends PythonTernaryClinicBuiltinNode {
558567
@Override
559568
protected ArgumentClinicProvider getArgumentClinic() {
560569
return StrfTimeNodeClinicProviderGen.INSTANCE;
@@ -873,15 +882,17 @@ private static String format(String format, int[] date) {
873882
}
874883

875884
@Specialization
876-
public String formatTime(String format, @SuppressWarnings("unused") PNone time) {
885+
public String formatTime(PythonModule module, String format, @SuppressWarnings("unused") PNone time,
886+
@Cached ReadAttributeFromDynamicObjectNode readZoneId) {
877887
if (format.indexOf(0) > -1) {
878888
throw raise(PythonBuiltinClassType.ValueError, ErrorMessages.EMBEDDED_NULL_CHARACTER);
879889
}
880-
return format(format, getIntLocalTimeStruct(PythonContext.get(this), (long) timeSeconds()));
890+
ZoneId zoneId = (ZoneId) readZoneId.execute(module, CURRENT_ZONE_ID);
891+
return format(format, getIntLocalTimeStruct(zoneId, (long) timeSeconds()));
881892
}
882893

883894
@Specialization
884-
public String formatTime(VirtualFrame frame, String format, PTuple time,
895+
public String formatTime(VirtualFrame frame, @SuppressWarnings("unused") PythonModule module, String format, PTuple time,
885896
@Cached SequenceStorageNodes.GetInternalObjectArrayNode getArray,
886897
@Cached SequenceStorageNodes.LenNode lenNode,
887898
@Cached PyNumberAsSizeNode asSizeNode) {
@@ -893,53 +904,57 @@ public String formatTime(VirtualFrame frame, String format, PTuple time,
893904
}
894905

895906
@Specialization
896-
public String formatTime(@SuppressWarnings("unused") String format, @SuppressWarnings("unused") Object time) {
907+
@SuppressWarnings("unused")
908+
public String formatTime(PythonModule module, String format, Object time) {
897909
throw raise(PythonBuiltinClassType.TypeError, ErrorMessages.TUPLE_OR_STRUCT_TIME_ARG_REQUIRED);
898910
}
899911
}
900912

901-
@Builtin(name = "mktime", minNumOfPositionalArgs = 1, doc = "mktime(tuple) -> floating point number\n\n" +
913+
@Builtin(name = "mktime", minNumOfPositionalArgs = 2, declaresExplicitSelf = true, doc = "mktime(tuple) -> floating point number\n\n" +
902914
"Convert a time tuple in local time to seconds since the Epoch.\n" +
903915
"Note that mktime(gmtime(0)) will not generally return zero for most\n" +
904916
"time zones; instead the returned value will either be equal to that\n" +
905917
"of the timezone or altzone attributes on the time module.")
906918
@GenerateNodeFactory
907-
abstract static class MkTimeNode extends PythonUnaryBuiltinNode {
919+
abstract static class MkTimeNode extends PythonBinaryBuiltinNode {
908920
private static final int ELEMENT_COUNT = 9;
909921

910922
@Specialization
911923
@ExplodeLoop
912-
double mktime(VirtualFrame frame, PTuple tuple,
924+
double mktime(VirtualFrame frame, PythonModule module, PTuple tuple,
913925
@Cached PyNumberAsSizeNode asSizeNode,
914-
@Cached GetObjectArrayNode getObjectArrayNode) {
926+
@Cached GetObjectArrayNode getObjectArrayNode,
927+
@Cached ReadAttributeFromDynamicObjectNode readZoneId) {
915928
Object[] items = getObjectArrayNode.execute(tuple);
916-
if (items.length != 9) {
917-
throw raise(PythonBuiltinClassType.TypeError, ErrorMessages.FUNC_TAKES_EXACTLY_D_ARGS, 9, items.length);
929+
if (items.length != ELEMENT_COUNT) {
930+
throw raise(PythonBuiltinClassType.TypeError, ErrorMessages.FUNC_TAKES_EXACTLY_D_ARGS, ELEMENT_COUNT, items.length);
918931
}
919-
int[] integers = new int[9];
932+
int[] integers = new int[ELEMENT_COUNT];
920933
for (int i = 0; i < ELEMENT_COUNT; i++) {
921934
integers[i] = asSizeNode.executeExact(frame, items[i]);
922935
}
923-
return op(getContext(), integers);
936+
ZoneId zoneId = (ZoneId) readZoneId.execute(module, CURRENT_ZONE_ID);
937+
return op(zoneId, integers);
924938
}
925939

926940
@TruffleBoundary
927-
private static long op(PythonContext context, int[] integers) {
941+
private static long op(ZoneId timeZone, int[] integers) {
928942
LocalDateTime localtime = LocalDateTime.of(integers[0], integers[1], integers[2], integers[3], integers[4], integers[5]);
929-
ZoneId timeZone = context.getEnv().getTimeZone();
930943
return localtime.toEpochSecond(timeZone.getRules().getOffset(localtime));
931944
}
932945
}
933946

934947
// time.ctime([secs])
935-
@Builtin(name = "ctime", maxNumOfPositionalArgs = 1)
948+
@Builtin(name = "ctime", maxNumOfPositionalArgs = 2, declaresExplicitSelf = true)
936949
@GenerateNodeFactory
937-
public abstract static class CTimeNode extends PythonBuiltinNode {
950+
public abstract static class CTimeNode extends PythonBinaryBuiltinNode {
938951

939952
@Specialization
940-
public String localtime(VirtualFrame frame, Object seconds,
953+
public static String localtime(VirtualFrame frame, PythonModule module, Object seconds,
954+
@Cached ReadAttributeFromDynamicObjectNode readZoneId,
941955
@Cached ToLongTime toLongTime) {
942-
return format(getIntLocalTimeStruct(PythonContext.get(this), toLongTime.execute(frame, seconds)));
956+
ZoneId zoneId = (ZoneId) readZoneId.execute(module, CURRENT_ZONE_ID);
957+
return format(getIntLocalTimeStruct(zoneId, toLongTime.execute(frame, seconds)));
943958
}
944959

945960
protected static String format(int[] tm) {
@@ -948,9 +963,9 @@ protected static String format(int[] tm) {
948963
}
949964

950965
// time.asctime([t])
951-
@Builtin(name = "asctime", maxNumOfPositionalArgs = 1)
966+
@Builtin(name = "asctime", maxNumOfPositionalArgs = 2, declaresExplicitSelf = true)
952967
@GenerateNodeFactory
953-
public abstract static class ASCTimeNode extends PythonBuiltinNode {
968+
public abstract static class ASCTimeNode extends PythonBinaryBuiltinNode {
954969

955970
static final String[] WDAY_NAME = new String[]{
956971
"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
@@ -961,20 +976,23 @@ public abstract static class ASCTimeNode extends PythonBuiltinNode {
961976
};
962977

963978
@Specialization
964-
public String localtime(@SuppressWarnings("unused") PNone time) {
965-
return format(getIntLocalTimeStruct(PythonContext.get(this), (long) timeSeconds()));
979+
public static String localtime(PythonModule module, @SuppressWarnings("unused") PNone time,
980+
@Cached ReadAttributeFromDynamicObjectNode readZoneId) {
981+
ZoneId zoneId = (ZoneId) readZoneId.execute(module, CURRENT_ZONE_ID);
982+
return format(getIntLocalTimeStruct(zoneId, (long) timeSeconds()));
966983
}
967984

968985
@Specialization
969-
public String localtime(VirtualFrame frame, PTuple time,
986+
public String localtime(VirtualFrame frame, @SuppressWarnings("unused") PythonModule module, PTuple time,
970987
@Cached SequenceStorageNodes.GetInternalObjectArrayNode getArray,
971988
@Cached SequenceStorageNodes.LenNode lenNode,
972989
@Cached PyNumberAsSizeNode asSizeNode) {
973990
return format(StrfTimeNode.checkStructtime(frame, time, getArray, lenNode, asSizeNode, getRaiseNode()));
974991
}
975992

976993
@Fallback
977-
public Object localtime(@SuppressWarnings("unused") Object time) {
994+
@SuppressWarnings("unused")
995+
public Object localtime(Object module, Object time) {
978996
throw raise(TypeError, ErrorMessages.TUPLE_OR_STRUCT_TIME_ARG_REQUIRED);
979997
}
980998

0 commit comments

Comments
 (0)