Dgraph4j datetime problem

Seems like dgraph4j deals with datetime with a problem:

String date = "2006-01-02T15:04:05.999999999";

DgraphProto.Value value = DgraphProto.Value.newBuilder().setDatetimeVal(ByteString.copyFromUtf8(date)).build();

DgraphProto.Mutation mutation = DgraphProto.Mutation.newBuilder()
               .addSet(DgraphProto.NQuad.newBuilder()
                       .setSubject("_:user")
                       .setPredicate("birthday")
                       .setObjectValue(value)).build();
txn.mutate(mutation);
txn.commit();

Debugging with the code above, dgraph raises an error like this:

Caused by: io.grpc.StatusRuntimeException: UNKNOWN: Time.UnmarshalBinary: unsupported version
	at io.grpc.Status.asRuntimeException(Status.java:526) ~[grpc-core-1.10.0.jar:1.10.0]
	at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onClose(ClientCalls.java:419) ~[grpc-stub-1.10.0.jar:1.10.0]
	at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:41) ~[grpc-core-1.10.0.jar:1.10.0]
	at io.grpc.internal.CensusStatsModule$StatsClientInterceptor$1$1.onClose(CensusStatsModule.java:684) ~[grpc-core-1.10.0.jar:1.10.0]
	at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:41) ~[grpc-core-1.10.0.jar:1.10.0]
	at io.grpc.internal.CensusTracingModule$TracingClientInterceptor$1$1.onClose(CensusTracingModule.java:391) ~[grpc-core-1.10.0.jar:1.10.0]
	at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:475) ~[grpc-core-1.10.0.jar:1.10.0]
	at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:63) ~[grpc-core-1.10.0.jar:1.10.0]
	at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.close(ClientCallImpl.java:557) ~[grpc-core-1.10.0.jar:1.10.0]
	at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.access$600(ClientCallImpl.java:478) ~[grpc-core-1.10.0.jar:1.10.0]
	at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:590) ~[grpc-core-1.10.0.jar:1.10.0]
	at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37) ~[grpc-core-1.10.0.jar:1.10.0]
	at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123) ~[grpc-core-1.10.0.jar:1.10.0]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_181]
	at java.lang.Thread.run(Thread.java:748) ~[?:1.8.0_181]

@deepak: Can you have a look at this?

The DgraphProto.Value proto representation dgraph expects for date values is Unix epoch time as Long (so 1136214246L in your case). This is different than what the JSON representation should be for the same value which is an RFC 3339 format String.

In case anyone is looking at this issue, and still would like to use the NQuad message classes in Java, I have ported the golang time.Time.MarshalBinary() method into Java. Sharing the code below:

public class DGraphDateTimeConverter {
    // https://golang.org/src/time/time.go search for unixToInternal
    private static final long UNIX_TO_INTERNAL = 62135638488L;

    public static ByteString convertTimeStampBinary(Long epochMillis) {
        // based on golang's time.Time.MarshalBinary()
        // https://golang.org/src/time/time.go?s=35686:35731#L1158

        int offsetMin = -1; // UTC
        long sec = UNIX_TO_INTERNAL + epochMillis / 1000;
        long nsec = epochMillis % 1000 * 1000000;

        byte[] byteArray = new byte[]{
                (byte) 1, // byte 0 : version
                (byte)(sec >> 56),   // bytes 1-8: seconds
                (byte)(sec >> 48),
                (byte)(sec >> 40),
                (byte)(sec >> 32),
                (byte)(sec >> 24),
                (byte)(sec >> 16),
                (byte)(sec >> 8),
                (byte)(sec),
                (byte)(nsec >> 24), // bytes 9-12: nanoseconds
                (byte)(nsec >> 16),
                (byte)(nsec >> 8),
                (byte)(nsec),
                (byte)(offsetMin >> 8), // bytes 13-14: zone offset in minutes
                (byte)(offsetMin),
        };

        return ByteString.copyFrom(byteArray);
    }
}

Hope this helps. I would like to put this method into dgraph4j as utlity method.

1 Like