Skip to content

Commit bf79a17

Browse files
cloud-fandavies
authored andcommitted
[SPARK-11752] [SQL] fix timezone problem for DateTimeUtils.getSeconds
code snippet to reproduce it: ``` TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")) val t = Timestamp.valueOf("1900-06-11 12:14:50.789") val us = fromJavaTimestamp(t) assert(getSeconds(us) === t.getSeconds) ``` it will be good to add a regression test for it, but the reproducing code need to change the default timezone, and even we change it back, the `lazy val defaultTimeZone` in `DataTimeUtils` is fixed. Author: Wenchen Fan <wenchen@databricks.com> Closes #9728 from cloud-fan/seconds. (cherry picked from commit 06f1fdb) Signed-off-by: Davies Liu <davies.liu@gmail.com>
1 parent b767cee commit bf79a17

File tree

2 files changed

+9
-7
lines changed

2 files changed

+9
-7
lines changed

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DateTimeUtils.scala

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -402,33 +402,35 @@ object DateTimeUtils {
402402
/**
403403
* Returns the microseconds since year zero (-17999) from microseconds since epoch.
404404
*/
405-
def absoluteMicroSecond(microsec: SQLTimestamp): SQLTimestamp = {
405+
private def absoluteMicroSecond(microsec: SQLTimestamp): SQLTimestamp = {
406406
microsec + toYearZero * MICROS_PER_DAY
407407
}
408408

409+
private def localTimestamp(microsec: SQLTimestamp): SQLTimestamp = {
410+
absoluteMicroSecond(microsec) + defaultTimeZone.getOffset(microsec / 1000) * 1000L
411+
}
412+
409413
/**
410414
* Returns the hour value of a given timestamp value. The timestamp is expressed in microseconds.
411415
*/
412416
def getHours(microsec: SQLTimestamp): Int = {
413-
val localTs = absoluteMicroSecond(microsec) + defaultTimeZone.getOffset(microsec / 1000) * 1000L
414-
((localTs / MICROS_PER_SECOND / 3600) % 24).toInt
417+
((localTimestamp(microsec) / MICROS_PER_SECOND / 3600) % 24).toInt
415418
}
416419

417420
/**
418421
* Returns the minute value of a given timestamp value. The timestamp is expressed in
419422
* microseconds.
420423
*/
421424
def getMinutes(microsec: SQLTimestamp): Int = {
422-
val localTs = absoluteMicroSecond(microsec) + defaultTimeZone.getOffset(microsec / 1000) * 1000L
423-
((localTs / MICROS_PER_SECOND / 60) % 60).toInt
425+
((localTimestamp(microsec) / MICROS_PER_SECOND / 60) % 60).toInt
424426
}
425427

426428
/**
427429
* Returns the second value of a given timestamp value. The timestamp is expressed in
428430
* microseconds.
429431
*/
430432
def getSeconds(microsec: SQLTimestamp): Int = {
431-
((absoluteMicroSecond(microsec) / MICROS_PER_SECOND) % 60).toInt
433+
((localTimestamp(microsec) / MICROS_PER_SECOND) % 60).toInt
432434
}
433435

434436
private[this] def isLeapYear(year: Int): Boolean = {

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ class DateTimeUtilsSuite extends SparkFunSuite {
326326
assert(getSeconds(c.getTimeInMillis * 1000) === 9)
327327
}
328328

329-
test("hours / miniute / seconds") {
329+
test("hours / minutes / seconds") {
330330
Seq(Timestamp.valueOf("2015-06-11 10:12:35.789"),
331331
Timestamp.valueOf("2015-06-11 20:13:40.789"),
332332
Timestamp.valueOf("1900-06-11 12:14:50.789"),

0 commit comments

Comments
 (0)