Skip to content

Commit

Permalink
DRILL-5002: Using hive's date functions on top of date column gives w…
Browse files Browse the repository at this point in the history
…rong results for local time-zone

closes #937
  • Loading branch information
vdiravka authored and Paul Rogers committed Sep 19, 2017
1 parent b2744a2 commit 4c99f0c
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,11 @@ public static JBlock getDrillObject(JCodeModel m, ObjectInspector oi,
<#elseif entry.hiveType == "TIMESTAMP">
JVar tsVar = jc._else().decl(m.directClass(java.sql.Timestamp.class.getCanonicalName()), "ts",
castedOI.invoke("getPrimitiveJavaObject").arg(returnValue));
jc._else().assign(returnValueHolder.ref("value"), tsVar.invoke("getTime"));
// Bringing relative timestamp value without timezone info to timestamp value in UTC, since Drill keeps date-time values in UTC
JVar localDateTimeVar = jc._else().decl(m.directClass(org.joda.time.LocalDateTime.class.getCanonicalName()), "localDateTime",
JExpr._new(m.directClass(org.joda.time.LocalDateTime.class.getCanonicalName())).arg(tsVar));
jc._else().assign(returnValueHolder.ref("value"), localDateTimeVar.invoke("toDateTime")
.arg(m.directClass(org.joda.time.DateTimeZone.class.getCanonicalName()).staticRef("UTC")).invoke("getMillis"));
<#elseif entry.hiveType == "DATE">
JVar dVar = jc._else().decl(m.directClass(java.sql.Date.class.getCanonicalName()), "d",
castedOI.invoke("getPrimitiveJavaObject").arg(returnValue));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,10 @@ public java.sql.Timestamp getPrimitiveJavaObject(Object o){
<#else>
final TimeStampHolder h = (TimeStampHolder) o;
</#if>
return new java.sql.Timestamp(h.value);
org.joda.time.LocalDateTime dateTime = new org.joda.time.LocalDateTime(h.value, org.joda.time.DateTimeZone.UTC);
// use "toDate()" to get java.util.Date object with exactly the same fields as this Joda date-time.
// See more in Javadoc for "LocalDateTime#toDate()"
return new java.sql.Timestamp(dateTime.toDate().getTime());
}

@Override
Expand All @@ -226,7 +229,10 @@ public TimestampWritable getPrimitiveWritableObject(Object o) {
<#else>
final TimeStampHolder h = (TimeStampHolder) o;
</#if>
return new TimestampWritable(new java.sql.Timestamp(h.value));
org.joda.time.LocalDateTime dateTime = new org.joda.time.LocalDateTime(h.value, org.joda.time.DateTimeZone.UTC);
// use "toDate()" to get java.util.Date object with exactly the same fields as this Joda date-time.
// See more in Javadoc for "LocalDateTime#toDate()"
return new TimestampWritable(new java.sql.Timestamp(dateTime.toDate().getTime()));
}

<#elseif entry.drillType == "Date">
Expand All @@ -240,7 +246,10 @@ public java.sql.Date getPrimitiveJavaObject(Object o){
<#else>
final DateHolder h = (DateHolder) o;
</#if>
return new java.sql.Date(h.value);
org.joda.time.LocalDate localDate = new org.joda.time.LocalDate(h.value, org.joda.time.DateTimeZone.UTC);
// Use "toDate()" to get java.util.Date object with exactly the same year the same year, month and day as Joda date.
// See more in Javadoc for "LocalDate#toDate()"
return new java.sql.Date(localDate.toDate().getTime());
}

@Override
Expand All @@ -253,7 +262,10 @@ public DateWritable getPrimitiveWritableObject(Object o) {
<#else>
final DateHolder h = (DateHolder) o;
</#if>
return new DateWritable(new java.sql.Date(h.value));
org.joda.time.LocalDate localDate = new org.joda.time.LocalDate(h.value, org.joda.time.DateTimeZone.UTC);
// Use "toDate()" to get java.util.Date object with exactly the same year the same year, month and day as Joda date.
// See more in Javadoc for "LocalDate#toDate()"
return new DateWritable(new java.sql.Date(localDate.toDate().getTime()));
}

<#else>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
Expand Down Expand Up @@ -26,6 +26,7 @@
import org.apache.drill.exec.compile.ClassTransformer;
import org.apache.drill.exec.hive.HiveTestBase;
import org.apache.drill.exec.server.options.OptionValue;
import org.joda.time.DateTime;
import org.junit.Test;

import java.util.List;
Expand Down Expand Up @@ -138,4 +139,44 @@ public void testEmbeddedHiveFunctionCall() throws Exception {
}
}

@Test
public void testLastDay() throws Exception {
testBuilder()
.sqlQuery("select last_day(to_date('1994-02-01','yyyy-MM-dd')) as `LAST_DAY` from (VALUES(1))")
.unOrdered()
.baselineColumns("LAST_DAY")
.baselineValues("1994-02-28")
.go();
}

@Test
public void testDatediff() throws Exception {
testBuilder()
.sqlQuery("select datediff(date '1996-03-01', timestamp '1997-02-10 17:32:00.0') as `DATEDIFF` from (VALUES(1))")
.unOrdered()
.baselineColumns("DATEDIFF")
.baselineValues(-346)
.go();
}

@Test
public void testFromUTCTimestamp() throws Exception {
testBuilder()
.sqlQuery("select from_utc_timestamp('1970-01-01 08:00:00','PST') as PST_TIMESTAMP from (VALUES(1))")
.unOrdered()
.baselineColumns("PST_TIMESTAMP")
.baselineValues(DateTime.parse("1970-01-01T00:00:00.0"))
.go();
}

@Test
public void testToUTCTimestamp() throws Exception {
testBuilder()
.sqlQuery("select to_utc_timestamp('1970-01-01 00:00:00','PST') as UTC_TIMESTAMP from (VALUES(1))")
.unOrdered()
.baselineColumns("UTC_TIMESTAMP")
.baselineValues(DateTime.parse("1970-01-01T08:00:00.0"))
.go();
}

}

0 comments on commit 4c99f0c

Please sign in to comment.