-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-8199][SPARK-8184][SPARK-8183][SPARK-8182][SPARK-8181][SPARK-8180][SPARK-8179][SPARK-8177][SPARK-8178][SPARK-9115][SQL] date functions #6981
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 all commits
d0e2f99
5ebb235
4d8049b
638596f
849fb41
c739788
b680db6
a5ea120
02efc5d
356df78
3bfac90
5fe74e1
a8edebd
f120415
eb6760d
5a105d9
7bc9d93
d9f8ac3
6f5d95c
f3e7a9f
7d9f0eb
10e4ad1
ccb723c
c42b444
ad17e96
f775f39
1a436c9
4fb66da
740af0e
1358cdc
ec87c69
0852655
1b2e540
b382267
d6aa14e
e223bc0
56c4a92
d01b977
2259299
523542d
0ad6db8
746b80a
cdfae27
fb98ba0
3c6ae2e
70238e0
ea6c110
4afc09c
6e0c78f
5983dcc
256c357
3e095ba
bb567b6
f7b4c8c
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 |
|---|---|---|
|
|
@@ -180,7 +180,19 @@ object FunctionRegistry { | |
|
|
||
| // datetime functions | ||
| expression[CurrentDate]("current_date"), | ||
| expression[CurrentTimestamp]("current_timestamp") | ||
| expression[CurrentTimestamp]("current_timestamp"), | ||
| expression[DateFormatClass]("date_format"), | ||
| expression[Day]("day"), | ||
|
Contributor
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. @rxin In Jira you mentioned there should be an alias. Can I just add
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. yes
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. btw please sort the expressions alphabetically |
||
| expression[DayInYear]("day_in_year"), | ||
| expression[Day]("day_of_month"), | ||
| expression[Hour]("hour"), | ||
| expression[Month]("month"), | ||
| expression[Minute]("minute"), | ||
| expression[Quarter]("quarter"), | ||
| expression[Second]("second"), | ||
| expression[WeekOfYear]("week_of_year"), | ||
| expression[Year]("year") | ||
|
|
||
| ) | ||
|
|
||
| val builtin: FunctionRegistry = { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,9 +17,15 @@ | |
|
|
||
| package org.apache.spark.sql.catalyst.expressions | ||
|
|
||
| import java.sql.Date | ||
| import java.text.SimpleDateFormat | ||
| import java.util.{Calendar, TimeZone} | ||
|
|
||
| import org.apache.spark.sql.catalyst.expressions.codegen.{CodeGenContext, GeneratedExpressionCode} | ||
| import org.apache.spark.sql.catalyst.InternalRow | ||
| import org.apache.spark.sql.catalyst.util.DateTimeUtils | ||
| import org.apache.spark.sql.types._ | ||
| import org.apache.spark.unsafe.types.UTF8String | ||
|
|
||
| /** | ||
| * Returns the current date at the start of query evaluation. | ||
|
|
@@ -54,3 +60,203 @@ case class CurrentTimestamp() extends LeafExpression { | |
| System.currentTimeMillis() * 1000L | ||
| } | ||
| } | ||
|
|
||
| case class Hour(child: Expression) extends UnaryExpression with ImplicitCastInputTypes { | ||
|
|
||
| override def inputTypes: Seq[AbstractDataType] = Seq(TimestampType) | ||
|
|
||
| override def dataType: DataType = IntegerType | ||
|
|
||
| override protected def nullSafeEval(timestamp: Any): Any = { | ||
| DateTimeUtils.getHours(timestamp.asInstanceOf[Long]) | ||
| } | ||
|
|
||
| override def genCode(ctx: CodeGenContext, ev: GeneratedExpressionCode): String = { | ||
| val dtu = DateTimeUtils.getClass.getName.stripSuffix("$") | ||
| defineCodeGen(ctx, ev, (c) => | ||
| s"""$dtu.getHours($c)""" | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| case class Minute(child: Expression) extends UnaryExpression with ImplicitCastInputTypes { | ||
|
|
||
| override def inputTypes: Seq[AbstractDataType] = Seq(TimestampType) | ||
|
|
||
| override def dataType: DataType = IntegerType | ||
|
|
||
| override protected def nullSafeEval(timestamp: Any): Any = { | ||
| DateTimeUtils.getMinutes(timestamp.asInstanceOf[Long]) | ||
| } | ||
|
|
||
| override def genCode(ctx: CodeGenContext, ev: GeneratedExpressionCode): String = { | ||
| val dtu = DateTimeUtils.getClass.getName.stripSuffix("$") | ||
| defineCodeGen(ctx, ev, (c) => | ||
| s"""$dtu.getMinutes($c)""" | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| case class Second(child: Expression) extends UnaryExpression with ImplicitCastInputTypes { | ||
|
|
||
| override def inputTypes: Seq[AbstractDataType] = Seq(TimestampType) | ||
|
|
||
| override def dataType: DataType = IntegerType | ||
|
|
||
| override protected def nullSafeEval(timestamp: Any): Any = { | ||
| DateTimeUtils.getSeconds(timestamp.asInstanceOf[Long]) | ||
| } | ||
|
|
||
| override protected def genCode(ctx: CodeGenContext, ev: GeneratedExpressionCode): String = { | ||
| val dtu = DateTimeUtils.getClass.getName.stripSuffix("$") | ||
| defineCodeGen(ctx, ev, (c) => | ||
| s"""$dtu.getSeconds($c)""" | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| case class DayInYear(child: Expression) extends UnaryExpression with ImplicitCastInputTypes { | ||
|
|
||
| override def inputTypes: Seq[AbstractDataType] = Seq(DateType) | ||
|
|
||
| override def dataType: DataType = IntegerType | ||
|
|
||
| override def prettyName: String = "day_in_year" | ||
|
|
||
| override protected def nullSafeEval(date: Any): Any = { | ||
| DateTimeUtils.getDayInYear(date.asInstanceOf[Int]) | ||
| } | ||
|
|
||
| override protected def genCode(ctx: CodeGenContext, ev: GeneratedExpressionCode): String = { | ||
| val dtu = DateTimeUtils.getClass.getName.stripSuffix("$") | ||
| defineCodeGen(ctx, ev, (c) => | ||
| s"""$dtu.getDayInYear($c)""" | ||
| ) | ||
| } | ||
| } | ||
|
|
||
|
|
||
| case class Year(child: Expression) extends UnaryExpression with ImplicitCastInputTypes { | ||
|
|
||
| override def inputTypes: Seq[AbstractDataType] = Seq(DateType) | ||
|
|
||
| override def dataType: DataType = IntegerType | ||
|
|
||
| override protected def nullSafeEval(date: Any): Any = { | ||
| DateTimeUtils.getYear(date.asInstanceOf[Int]) | ||
| } | ||
|
|
||
| override protected def genCode(ctx: CodeGenContext, ev: GeneratedExpressionCode): String = { | ||
| val dtu = DateTimeUtils.getClass.getName.stripSuffix("$") | ||
| defineCodeGen(ctx, ev, (c) => | ||
| s"""$dtu.getYear($c)""" | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| case class Quarter(child: Expression) extends UnaryExpression with ImplicitCastInputTypes { | ||
|
|
||
| override def inputTypes: Seq[AbstractDataType] = Seq(DateType) | ||
|
|
||
| override def dataType: DataType = IntegerType | ||
|
|
||
| override protected def nullSafeEval(date: Any): Any = { | ||
| DateTimeUtils.getQuarter(date.asInstanceOf[Int]) | ||
| } | ||
|
|
||
| override protected def genCode(ctx: CodeGenContext, ev: GeneratedExpressionCode): String = { | ||
| val dtu = DateTimeUtils.getClass.getName.stripSuffix("$") | ||
| defineCodeGen(ctx, ev, (c) => | ||
| s"""$dtu.getQuarter($c)""" | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| case class Month(child: Expression) extends UnaryExpression with ImplicitCastInputTypes { | ||
|
|
||
| override def inputTypes: Seq[AbstractDataType] = Seq(DateType) | ||
|
|
||
| override def dataType: DataType = IntegerType | ||
|
|
||
| override protected def nullSafeEval(date: Any): Any = { | ||
| DateTimeUtils.getMonth(date.asInstanceOf[Int]) | ||
| } | ||
|
|
||
| override protected def genCode(ctx: CodeGenContext, ev: GeneratedExpressionCode): String = { | ||
| val dtu = DateTimeUtils.getClass.getName.stripSuffix("$") | ||
| defineCodeGen(ctx, ev, (c) => | ||
| s"""$dtu.getMonth($c)""" | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| case class Day(child: Expression) extends UnaryExpression with ImplicitCastInputTypes { | ||
|
|
||
| override def inputTypes: Seq[AbstractDataType] = Seq(DateType) | ||
|
|
||
| override def dataType: DataType = IntegerType | ||
|
|
||
| override protected def nullSafeEval(date: Any): Any = { | ||
| DateTimeUtils.getDayOfMonth(date.asInstanceOf[Int]) | ||
| } | ||
|
|
||
| override protected def genCode(ctx: CodeGenContext, ev: GeneratedExpressionCode): String = { | ||
| val dtu = DateTimeUtils.getClass.getName.stripSuffix("$") | ||
| defineCodeGen(ctx, ev, (c) => | ||
| s"""$dtu.getDayOfMonth($c)""" | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| case class WeekOfYear(child: Expression) extends UnaryExpression with ImplicitCastInputTypes { | ||
|
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. make sure you override prettyName here too |
||
|
|
||
| override def inputTypes: Seq[AbstractDataType] = Seq(DateType) | ||
|
|
||
| override def dataType: DataType = IntegerType | ||
|
|
||
| override def prettyName: String = "week_of_year" | ||
|
|
||
| override protected def nullSafeEval(date: Any): Any = { | ||
| val c = Calendar.getInstance(TimeZone.getTimeZone("UTC")) | ||
| c.setFirstDayOfWeek(Calendar.MONDAY) | ||
| c.setMinimalDaysInFirstWeek(4) | ||
| c.setTimeInMillis(date.asInstanceOf[Int] * 1000L * 3600L * 24L) | ||
| c.get(Calendar.WEEK_OF_YEAR) | ||
| } | ||
|
|
||
| override def genCode(ctx: CodeGenContext, ev: GeneratedExpressionCode): String = | ||
| nullSafeCodeGen(ctx, ev, (time) => { | ||
| val cal = classOf[Calendar].getName | ||
| val c = ctx.freshName("cal") | ||
| s""" | ||
| $cal $c = $cal.getInstance(java.util.TimeZone.getTimeZone("UTC")); | ||
| $c.setFirstDayOfWeek($cal.MONDAY); | ||
| $c.setMinimalDaysInFirstWeek(4); | ||
| $c.setTimeInMillis($time * 1000L * 3600L * 24L); | ||
| ${ev.primitive} = $c.get($cal.WEEK_OF_YEAR); | ||
| """ | ||
| }) | ||
| } | ||
|
|
||
| case class DateFormatClass(left: Expression, right: Expression) extends BinaryExpression | ||
|
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 not just DateFormat?
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. make sure you override prettyName and use "date_format"
Contributor
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. Name has to be |
||
| with ImplicitCastInputTypes { | ||
|
|
||
| override def dataType: DataType = StringType | ||
|
|
||
| override def inputTypes: Seq[AbstractDataType] = Seq(TimestampType, StringType) | ||
|
|
||
| override def prettyName: String = "date_format" | ||
|
|
||
| override protected def nullSafeEval(timestamp: Any, format: Any): Any = { | ||
| val sdf = new SimpleDateFormat(format.toString) | ||
| UTF8String.fromString(sdf.format(new Date(timestamp.asInstanceOf[Long] / 1000))) | ||
| } | ||
|
|
||
| override def genCode(ctx: CodeGenContext, ev: GeneratedExpressionCode): String = { | ||
| val sdf = classOf[SimpleDateFormat].getName | ||
| defineCodeGen(ctx, ev, (timestamp, format) => { | ||
| s"""UTF8String.fromString((new $sdf($format.toString())) | ||
| .format(new java.sql.Date($timestamp / 1000)))""" | ||
| }) | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ignore_unicode_prefix