Skip to content

Commit

Permalink
[Truffle] Some more work on Time.
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisseaton committed Feb 15, 2015
1 parent 5f3ff7c commit ae6e152
Show file tree
Hide file tree
Showing 18 changed files with 54 additions and 35 deletions.
18 changes: 11 additions & 7 deletions core/src/main/java/org/jruby/RubyTime.java
Expand Up @@ -832,17 +832,21 @@ public RubyBoolean isdst() {

@JRubyMethod
public IRubyObject zone() {
Ruby runtime = getRuntime();
if (isTzRelative) return runtime.getNil();

String envTZ = getEnvTimeZone(runtime).toString();
final String zone = RubyTime.zoneHelper(getEnvTimeZone(getRuntime()).toString(), dt, isTzRelative);
if (zone == null) return getRuntime().getNil();
return getRuntime().newString();
}

public static String zoneHelper(String envTZ, DateTime dt, boolean isTzRelative) {
if (isTzRelative) return null;

// see declaration of SHORT_TZNAME
if (SHORT_STD_TZNAME.containsKey(envTZ) && ! dt.getZone().toTimeZone().inDaylightTime(dt.toDate())) {
return runtime.newString(SHORT_STD_TZNAME.get(envTZ));
return SHORT_STD_TZNAME.get(envTZ);
}

if (SHORT_DL_TZNAME.containsKey(envTZ) && dt.getZone().toTimeZone().inDaylightTime(dt.toDate())) {
return runtime.newString(SHORT_DL_TZNAME.get(envTZ));
return SHORT_DL_TZNAME.get(envTZ);
}

String zone = dt.getZone().getShortName(dt.getMillis());
Expand All @@ -865,7 +869,7 @@ public IRubyObject zone() {
}
}

return runtime.newString(zone);
return zone;
}

public void setDateTime(DateTime dt) {
Expand Down
2 changes: 0 additions & 2 deletions spec/truffle/tags/core/time/_dump_tags.txt
@@ -1,3 +1 @@
fails:Time#_dump dumps a Time object to a bytestring
fails:Time#_dump dumps an array with a time as second element
fails:Time#_dump dumps like MRI's marshaled time format
1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/getgm_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/getutc_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/gmtime_tags.txt

This file was deleted.

1 change: 1 addition & 0 deletions spec/truffle/tags/core/time/inspect_tags.txt
@@ -0,0 +1 @@
fails:Time#inspect formats the fixed offset time following the pattern 'yyyy-MM-dd HH:mm:ss +/-HHMM'
1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/local_tags.txt
@@ -1,4 +1,3 @@
fails:Time.local creates a time based on given values, interpreted in the local time zone
fails:Time.local respects rare old timezones
fails:Time.local creates a time based on given C-style gmtime arguments, interpreted in the local time zone
fails:Time.local creates the correct time just before dst change
Expand Down
1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/mktime_tags.txt
@@ -1,4 +1,3 @@
fails:Time.mktime creates a time based on given values, interpreted in the local time zone
fails:Time.mktime respects rare old timezones
fails:Time.mktime creates a time based on given C-style gmtime arguments, interpreted in the local time zone
fails:Time.mktime creates the correct time just before dst change
Expand Down
1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/new_tags.txt
@@ -1,4 +1,3 @@
fails:Time.new creates a time based on given values, interpreted in the local time zone
fails:Time.new respects rare old timezones
fails:Time.new accepts 1 argument (year)
fails:Time.new accepts 2 arguments (year, month)
Expand Down
2 changes: 1 addition & 1 deletion spec/truffle/tags/core/time/plus_tags.txt
@@ -1,4 +1,3 @@
fails:Time#+ increments the time by the specified amount as rational numbers
fails:Time#+ is a commutative operator
fails:Time#+ adds a negative Float
fails:Time#+ accepts arguments that can be coerced into Rational
Expand All @@ -11,3 +10,4 @@ fails:Time#+ maintains microseconds precision
fails:Time#+ maintains nanoseconds precision
fails:Time#+ maintains subseconds precision
fails:Time#+ maintains precision
fails:Time#+ increments the time by the specified amount as rational numbers
5 changes: 4 additions & 1 deletion spec/truffle/tags/core/time/strftime_tags.txt
@@ -1,4 +1,3 @@
fails:Time#strftime returns the timezone with %Z
fails:Time#strftime returns the fractional seconds digits, default is 9 digits (nanosecond) with %N
fails:Time#strftime with %L formats the milliseconds of a second
fails:Time#strftime with %N formats the nanoseconds of of the second with %N
Expand All @@ -10,3 +9,7 @@ fails:Time#strftime with %z formats a UTC time offset as '+0000'
fails:Time#strftime with %z formats a local time with positive UTC offset as '+HHMM'
fails:Time#strftime with %z formats a local time with negative UTC offset as '-HHMM'
fails:Time#strftime with %z rounds fixed offset to the nearest second
fails:Time#strftime with %z formats a time with fixed positive offset as '+HHMM'
fails:Time#strftime with %z formats a time with fixed negative offset as '-HHMM'
fails:Time#strftime with %z formats a time with fixed offset as '+/-HH:MM' with ':' specifier
fails:Time#strftime with %z formats a time with fixed offset as '+/-HH:MM:SS' with '::' specifier
1 change: 1 addition & 0 deletions spec/truffle/tags/core/time/to_s_tags.txt
@@ -0,0 +1 @@
fails:Time#to_s formats the fixed offset time following the pattern 'yyyy-MM-dd HH:mm:ss +/-HHMM'
1 change: 0 additions & 1 deletion spec/truffle/tags/core/time/utc_tags.txt
Expand Up @@ -43,4 +43,3 @@ fails:Time.utc handles fractional microseconds as a Float
fails:Time.utc handles fractional microseconds as a Rational
fails:Time.utc ignores fractional seconds if a passed whole number of microseconds
fails:Time.utc ignores fractional seconds if a passed fractional number of microseconds
fails:Time#utc returns the utc representation of time
2 changes: 0 additions & 2 deletions spec/truffle/tags/core/time/zone_tags.txt
@@ -1,7 +1,5 @@
fails:Time#zone returns the time zone used for time
fails:Time#zone returns nil for a Time with a fixed offset
fails:Time#zone returns the correct timezone for a local time
fails:Time#zone returns nil when getting the local time with a fixed offset
fails:Time#zone returns UTC when called on a UTC time
fails:Time#zone Encoding.default_internal is set returns the string with the default internal encoding
fails:Time#zone Encoding.default_internal is set doesn't raise errors for a Time with a fixed offset
Expand Up @@ -32,7 +32,7 @@ public JodaDateTimeToRubyTimeNode(RubyContext context, SourceSection sourceSecti

public RubyTime toDateTime(VirtualFrame frame, DateTime dateTime) {
final long miliseconds = dateTime.getMillis();
final RubyTime time = new RubyTime(context.getCoreLibrary().getTimeClass(), TimeOperations.millisecondsToSeconds(miliseconds), TimeOperations.nanosecondsInCurrentSecond(miliseconds));
final RubyTime time = new RubyTime(context.getCoreLibrary().getTimeClass(), TimeOperations.millisecondsToSeconds(miliseconds), TimeOperations.nanosecondsInCurrentSecond(miliseconds), dateTime.getZone());
writeIsGMTNode.execute(time, dateTime.getZone() == DateTimeZone.UTC);
writeOffsetNode.execute(time, dateTime.getZone().getOffset(miliseconds));
return time;
Expand Down
Expand Up @@ -51,28 +51,28 @@ public DateTime toDateTime(VirtualFrame frame, RubyTime time) {
isGMT = false;
}

return toDateTime(time.getSeconds(),
return toDateTime(time.getZone(), time.getSeconds(),
time.getNanoseconds(),
isGMT,
readOffsetNode.execute(time));
}

@CompilerDirectives.TruffleBoundary
private DateTime toDateTime(long seconds, long nanoseconds, boolean isGMT, Object offset) {
private DateTime toDateTime(DateTimeZone zone, long seconds, long nanoseconds, boolean isGMT, Object offset) {
long time = TimeOperations.secondsAndNanosecondsToMiliseconds(seconds, nanoseconds);

final DateTimeZone dateTimeZone;

if (isGMT || offset == null || offset == context.getCoreLibrary().getNilObject()) {
dateTimeZone = DateTimeZone.UTC;
dateTimeZone = zone;
} else if (offset instanceof Integer) {
final int intOffset = (int) offset;

// TODO CS 14-Feb-15 why is this negative? Rbx has some comments about having to reserve it
dateTimeZone = DateTimeZone.forOffsetMillis(-intOffset);
dateTimeZone = zone;//DateTimeZone.forOffsetMillis(-intOffset);

// TODO CS 14-Feb-15 we seem to need to actually apply the offset here as well? And twice?
time -= dateTimeZone.getOffset(time) * 2;
//time -= dateTimeZone.getOffset(time) * 2;
} else {
throw new UnsupportedOperationException(offset.getClass().getName());
}
Expand Down
Expand Up @@ -17,6 +17,7 @@
import org.joda.time.DateTimeZone;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNode;
import org.jruby.truffle.nodes.objectstorage.WriteHeadObjectFieldNode;
import org.jruby.truffle.runtime.DebugOperations;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.*;
import org.jruby.util.ByteList;
Expand All @@ -43,9 +44,13 @@ public TimeSNowPrimitiveNode(TimeSNowPrimitiveNode prev) {
@Specialization
public RubyTime timeSNow(RubyClass timeClass) {
final long milliseconds = System.currentTimeMillis();
// TODO CS 14-Feb-15 uses debug send
final DateTimeZone zone = org.jruby.RubyTime.getTimeZoneFromTZString(getContext().getRuntime(),
DebugOperations.send(getContext(), getContext().getCoreLibrary().getENV(), "[]", null, getContext().makeString("TZ")).toString());
return new RubyTime(timeClass,
TimeOperations.millisecondsToSeconds(milliseconds),
TimeOperations.millisecondsToNanoseconds(TimeOperations.millisecondsInCurrentSecond(milliseconds)));
TimeOperations.millisecondsToNanoseconds(TimeOperations.millisecondsInCurrentSecond(milliseconds)),
zone);
}

}
Expand All @@ -69,7 +74,7 @@ public TimeSDupPrimitiveNode(TimeSDupPrimitiveNode prev) {

@Specialization
public RubyTime timeSDup(RubyTime other) {
final RubyTime time = new RubyTime(getContext().getCoreLibrary().getTimeClass(), other.getSeconds(), other.getNanoseconds());
final RubyTime time = new RubyTime(getContext().getCoreLibrary().getTimeClass(), other.getSeconds(), other.getNanoseconds(), other.getZone());
writeIsGMTNode.execute(time, readIsGMTNode.execute(other));
writeOffsetNode.execute(time, readOffsetNode.execute(other));
return time;
Expand Down Expand Up @@ -109,7 +114,8 @@ public RubyTime timeSSpecific(int seconds, long nanoseconds, Object isGMT, Objec
@Specialization
public RubyTime timeSSpecific(long seconds, long nanoseconds, Object isGMT, Object offset) {
// TODO(CS): overflow checks here in Rbx
final RubyTime time = new RubyTime(getContext().getCoreLibrary().getTimeClass(), seconds, nanoseconds);
// TODO CS 14-Feb-15 uses UTC
final RubyTime time = new RubyTime(getContext().getCoreLibrary().getTimeClass(), seconds, nanoseconds, DateTimeZone.UTC);
writeIsGMTNode.execute(time, isGMT);
writeOffsetNode.execute(time, offset);
return time;
Expand Down Expand Up @@ -178,15 +184,17 @@ public RubyArray timeDecompose(VirtualFrame frame, RubyTime time) {
@CompilerDirectives.TruffleBoundary
public Object[] decompose(DateTime dateTime) {
final int sec = dateTime.getSecondOfMinute();
final int min = dateTime.getMinuteOfDay();
final int min = dateTime.getMinuteOfHour();
final int hour = dateTime.getHourOfDay();
final int day = dateTime.getDayOfMonth();
final int month = dateTime.getMonthOfYear();
final int year = dateTime.getYear();
final int wday = dateTime.getDayOfWeek();
final int yday = dateTime.getDayOfYear();
final Object isdst = getContext().getCoreLibrary().getNilObject();
final Object zone = getContext().getCoreLibrary().getNilObject();
final boolean isdst = false;
// TODO CS 14-Feb-15 uses debug send
final String envTimeZoneString = DebugOperations.send(getContext(), getContext().getCoreLibrary().getENV(), "[]", null, getContext().makeString("TZ")).toString();
final RubyString zone = getContext().makeString(org.jruby.RubyTime.zoneHelper(envTimeZoneString, dateTime, false));
return new Object[]{sec, min, hour, day, month, year, wday, yday, isdst, zone};
}

Expand Down Expand Up @@ -256,7 +264,10 @@ public RubyTime timeSFromArray(VirtualFrame frame, int sec, int min, int hour, i
if (fromgmt) {
dateTime = new DateTime(year, month, mday, hour, min, sec, DateTimeZone.UTC);
} else {
dateTime = new DateTime(year, month, mday, hour, min, sec, DateTimeZone.forOffsetHours(isdst));
// TODO CS 14-Feb-15 uses debug send
final DateTimeZone zone = org.jruby.RubyTime.getTimeZoneFromTZString(getContext().getRuntime(),
DebugOperations.send(getContext(), getContext().getCoreLibrary().getENV(), "[]", null, getContext().makeString("TZ")).toString());
dateTime = new DateTime(year, month, mday, hour, min, sec, zone);
}
return toRubyTime.toDateTime(frame, dateTime);
}
Expand Down
14 changes: 12 additions & 2 deletions truffle/src/main/java/org/jruby/truffle/runtime/core/RubyTime.java
Expand Up @@ -9,6 +9,7 @@
*/
package org.jruby.truffle.runtime.core;

import org.joda.time.DateTimeZone;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
Expand All @@ -17,18 +18,20 @@ public class RubyTime extends RubyBasicObject {

private long seconds;
private long nanoseconds;
private DateTimeZone zone;

public RubyTime(RubyClass timeClass, long seconds, long nanoseconds) {
public RubyTime(RubyClass timeClass, long seconds, long nanoseconds, DateTimeZone zone) {
super(timeClass);
this.seconds = seconds;
this.nanoseconds = nanoseconds;
this.zone = zone;
}

public static class TimeAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
return new RubyTime(rubyClass, 0, 0);
return new RubyTime(rubyClass, 0, 0, DateTimeZone.UTC);
}

}
Expand All @@ -49,4 +52,11 @@ public void setNanoseconds(long nanoseconds) {
this.nanoseconds = nanoseconds;
}

public DateTimeZone getZone() {
return zone;
}

public void setZone(DateTimeZone zone) {
this.zone = zone;
}
}

0 comments on commit ae6e152

Please sign in to comment.