-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-26456][SQL] Cast date/timestamp to string by Date/TimestampFormatter #23391
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 16 commits
e09c972
697688a
fcffc12
f0a9fe7
5f0b0a3
17a32a3
9d90d3f
038ad80
f6308f6
9f85ac6
d348c07
36c9f9a
4580c25
56bdae4
8541602
ecf0e89
c3066e1
eed40d7
94cad6a
0de72c8
1156291
5ae58a3
78c3961
2397401
206c955
483e95b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -88,11 +88,18 @@ class LegacyFallbackDateFormatter( | |
| } | ||
|
|
||
| object DateFormatter { | ||
| val defaultPattern: String = "yyyy-MM-dd" | ||
| val defaultLocale: Locale = Locale.US | ||
|
|
||
| def apply(format: String, locale: Locale): DateFormatter = { | ||
| if (SQLConf.get.legacyTimeParserEnabled) { | ||
|
||
| new LegacyFallbackDateFormatter(format, locale) | ||
| } else { | ||
| new Iso8601DateFormatter(format, locale) | ||
| } | ||
| } | ||
|
|
||
| def apply(format: String): DateFormatter = apply(format, defaultLocale) | ||
|
|
||
| def apply(): DateFormatter = apply(defaultPattern) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both formatters seems to use thread safe implementations. You could consider just returning cached instances here.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At the moment, both formatters are created per partition at least not per row. Do you think it makes sense to cache them?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, lets leave it for now. |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42,7 +42,7 @@ sealed trait TimestampFormatter extends Serializable { | |
| @throws(classOf[ParseException]) | ||
| @throws(classOf[DateTimeParseException]) | ||
| @throws(classOf[DateTimeException]) | ||
| def parse(s: String): Long // returns microseconds since epoch | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why remove this comment?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. because it duplicates method description above. |
||
| def parse(s: String): Long | ||
| def format(us: Long): String | ||
| } | ||
|
|
||
|
|
@@ -105,11 +105,22 @@ class LegacyFallbackTimestampFormatter( | |
| } | ||
|
|
||
| object TimestampFormatter { | ||
| val defaultPattern: String = "yyyy-MM-dd HH:mm:ss" | ||
| val defaultLocale: Locale = Locale.US | ||
|
|
||
| def apply(format: String, timeZone: TimeZone, locale: Locale): TimestampFormatter = { | ||
| if (SQLConf.get.legacyTimeParserEnabled) { | ||
| new LegacyFallbackTimestampFormatter(format, timeZone, locale) | ||
| } else { | ||
| new Iso8601TimestampFormatter(format, timeZone, locale) | ||
| } | ||
| } | ||
|
|
||
| def apply(format: String, timeZone: TimeZone): TimestampFormatter = { | ||
| apply(format, timeZone, defaultLocale) | ||
| } | ||
|
|
||
| def apply(timeZone: TimeZone): TimestampFormatter = { | ||
| apply(defaultPattern, timeZone, defaultLocale) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,8 +30,7 @@ import org.apache.spark.sql.catalyst.{InternalRow, QueryPlanningTracker} | |
| import org.apache.spark.sql.catalyst.analysis.UnsupportedOperationChecker | ||
| import org.apache.spark.sql.catalyst.plans.logical.{LogicalPlan, ReturnAnswer} | ||
| import org.apache.spark.sql.catalyst.rules.Rule | ||
| import org.apache.spark.sql.catalyst.util.DateTimeUtils | ||
| import org.apache.spark.sql.catalyst.util.truncatedString | ||
| import org.apache.spark.sql.catalyst.util.{truncatedString, DateFormatter, DateTimeUtils, TimestampFormatter} | ||
| import org.apache.spark.sql.execution.command.{DescribeTableCommand, ExecutedCommandExec, ShowTablesCommand} | ||
| import org.apache.spark.sql.execution.exchange.{EnsureRequirements, ReuseExchange} | ||
| import org.apache.spark.sql.internal.SQLConf | ||
|
|
@@ -111,6 +110,9 @@ class QueryExecution( | |
| protected def stringOrError[A](f: => A): String = | ||
| try f.toString catch { case e: AnalysisException => e.toString } | ||
|
|
||
| private val dateFormatter = DateFormatter() | ||
|
||
| private val timestampFormatter = TimestampFormatter( | ||
| DateTimeUtils.getTimeZone(sparkSession.sessionState.conf.sessionLocalTimeZone)) | ||
|
|
||
| /** | ||
| * Returns the result as a hive compatible sequence of strings. This is used in tests and | ||
|
|
@@ -184,11 +186,9 @@ class QueryExecution( | |
| toHiveStructString((key, kType)) + ":" + toHiveStructString((value, vType)) | ||
| }.toSeq.sorted.mkString("{", ",", "}") | ||
| case (null, _) => "NULL" | ||
| case (d: Date, DateType) => | ||
| DateTimeUtils.dateToString(DateTimeUtils.fromJavaDate(d)) | ||
| case (d: Date, DateType) => dateFormatter.format(DateTimeUtils.fromJavaDate(d)) | ||
| case (t: Timestamp, TimestampType) => | ||
| DateTimeUtils.timestampToString(DateTimeUtils.fromJavaTimestamp(t), | ||
| DateTimeUtils.getTimeZone(sparkSession.sessionState.conf.sessionLocalTimeZone)) | ||
| DateTimeUtils.timestampToString(timestampFormatter, DateTimeUtils.fromJavaTimestamp(t)) | ||
| case (bin: Array[Byte], BinaryType) => new String(bin, StandardCharsets.UTF_8) | ||
| case (decimal: java.math.BigDecimal, DecimalType()) => formatDecimal(decimal) | ||
| case (interval, CalendarIntervalType) => interval.toString | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.