Skip to content
Snippets Groups Projects
Commit 06f1fdba authored by Wenchen Fan's avatar Wenchen Fan Committed by Davies Liu
Browse files

[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.
parent 0e79604a
No related branches found
No related tags found
No related merge requests found
......@@ -395,16 +395,19 @@ object DateTimeUtils {
/**
* Returns the microseconds since year zero (-17999) from microseconds since epoch.
*/
def absoluteMicroSecond(microsec: SQLTimestamp): SQLTimestamp = {
private def absoluteMicroSecond(microsec: SQLTimestamp): SQLTimestamp = {
microsec + toYearZero * MICROS_PER_DAY
}
private def localTimestamp(microsec: SQLTimestamp): SQLTimestamp = {
absoluteMicroSecond(microsec) + defaultTimeZone.getOffset(microsec / 1000) * 1000L
}
/**
* Returns the hour value of a given timestamp value. The timestamp is expressed in microseconds.
*/
def getHours(microsec: SQLTimestamp): Int = {
val localTs = absoluteMicroSecond(microsec) + defaultTimeZone.getOffset(microsec / 1000) * 1000L
((localTs / MICROS_PER_SECOND / 3600) % 24).toInt
((localTimestamp(microsec) / MICROS_PER_SECOND / 3600) % 24).toInt
}
/**
......@@ -412,8 +415,7 @@ object DateTimeUtils {
* microseconds.
*/
def getMinutes(microsec: SQLTimestamp): Int = {
val localTs = absoluteMicroSecond(microsec) + defaultTimeZone.getOffset(microsec / 1000) * 1000L
((localTs / MICROS_PER_SECOND / 60) % 60).toInt
((localTimestamp(microsec) / MICROS_PER_SECOND / 60) % 60).toInt
}
/**
......@@ -421,7 +423,7 @@ object DateTimeUtils {
* microseconds.
*/
def getSeconds(microsec: SQLTimestamp): Int = {
((absoluteMicroSecond(microsec) / MICROS_PER_SECOND) % 60).toInt
((localTimestamp(microsec) / MICROS_PER_SECOND) % 60).toInt
}
private[this] def isLeapYear(year: Int): Boolean = {
......
......@@ -358,7 +358,7 @@ class DateTimeUtilsSuite extends SparkFunSuite {
assert(getSeconds(c.getTimeInMillis * 1000) === 9)
}
test("hours / miniute / seconds") {
test("hours / minutes / seconds") {
Seq(Timestamp.valueOf("2015-06-11 10:12:35.789"),
Timestamp.valueOf("2015-06-11 20:13:40.789"),
Timestamp.valueOf("1900-06-11 12:14:50.789"),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment