RubyTimeToDateTimeNode.java
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.nodes.rubinius;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.source.SourceSection;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.jruby.truffle.nodes.cast.BooleanCastNode;
import org.jruby.truffle.nodes.cast.BooleanCastNodeFactory;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyTime;
import org.jruby.truffle.runtime.core.TimeOperations;
/**
* Supports {@link TimePrimitiveNodes} by converting a {@link RubyTime} to a {@link DateTime}. We use a node because
* doing this requires accessing instance variables, which we want to use an inline cache for.
*/
class RubyTimeToDateTimeNode extends Node {
private final RubyContext context;
@Child protected ReadHeadObjectFieldNode readIsGMTNode = new ReadHeadObjectFieldNode("@is_gmt");
@Child protected ReadHeadObjectFieldNode readOffsetNode = new ReadHeadObjectFieldNode("@offset");
public RubyTimeToDateTimeNode(RubyContext context, SourceSection sourceSection) {
this.context = context;
}
public DateTime toDateTime(VirtualFrame frame, RubyTime time) {
final Object isGMTObject = readIsGMTNode.execute(time);
// The @is_gmt instance variable is only for internal use so we don't need a full cast here
final boolean isGMT;
if (isGMTObject instanceof Boolean && ((boolean) isGMTObject)) {
isGMT = true;
} else {
isGMT = false;
}
return toDateTime(time.getSeconds(),
time.getNanoseconds(),
isGMT,
readOffsetNode.execute(time));
}
@CompilerDirectives.TruffleBoundary
private DateTime toDateTime(long seconds, long nanoseconds, boolean isGMT, Object offset) {
final DateTimeZone dateTimeZone;
if (isGMT) {
dateTimeZone = DateTimeZone.UTC;
} else {
dateTimeZone = org.jruby.RubyTime.getLocalTimeZone(context.getRuntime());
}
return new DateTime(TimeOperations.secondsAndNanosecondsToMiliseconds(seconds, nanoseconds), dateTimeZone);
}
}