Skip to content

Commit

Permalink
Remove negative value limitation. Added documentation to BuiltinFunct…
Browse files Browse the repository at this point in the history
…ions.md
  • Loading branch information
alancai98 committed Dec 24, 2020
1 parent 0e08abd commit 550121f
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 22 deletions.
59 changes: 59 additions & 0 deletions docs/user/BuiltInFunctions.md
Original file line number Diff line number Diff line change
Expand Up @@ -764,3 +764,62 @@ Examples
```sql
UTCNOW() -- 2017-10-13T16:02:11.123Z
```

### UNIX_TIMESTAMP

With no `timestamp` argument, returns the number of seconds since the last epoch ('1970-01-01 00:00:00' UTC).

With a `timestamp` argument, returns the number of seconds from the last epoch to the given `timestamp`
(possibly negative).

Signature : `UNIX_TIMESTAMP: [Timestamp] -> Integer|Decimal`

Header : `UNIX_TIMESTAMP([timestamp])`

Purpose : `UNIX_TIMESTAMP()` called without a `timestamp` argument returns the number of whole seconds since the last
epoch ('1970-01-01 00:00:00' UTC) as an Integer using `UTCNOW`.

`UNIX_TIMESTAMP()` called with a `timestamp` argument returns returns the number of seconds from the last epoch to the
`timestamp` argument.
If given a `timestamp` before the last epoch, `UNIX_TIMESTAMP` will return the number of seconds before the last epoch as a negative
number.
The return value will be a Decimal if and only if the given `timestamp` has a fractional seconds part.

Examples :
```sql
UNIX_TIMESTAMP() -- 1507910531 (if current time is `2017-10-13T16:02:11Z`; # of seconds since last epoch as an Integer)
UNIX_TIMESTAMP(`2020T`) -- 1577836800 (seconds from 2020 to the last epoch as an Integer)
UNIX_TIMESTAMP(`2020-01T`) -- ''
UNIX_TIMESTAMP(`2020-01-01T`) -- ''
UNIX_TIMESTAMP(`2020-01-01T00:00Z`) -- ''
UNIX_TIMESTAMP(`2020-01-01T00:00:00Z`) -- ''
UNIX_TIMESTAMP(`2020-01-01T00:00:00.0Z`) -- 1577836800. (seconds from 2020 to the last epoch as a Decimal)
UNIX_TIMESTAMP(`2020-01-01T00:00:00.00Z`) -- ''
UNIX_TIMESTAMP(`2020-01-01T00:00:00.000Z`) -- ''
UNIX_TIMESTAMP(`2020-01-01T00:00:00.100Z`) -- 1577836800.1
UNIX_TIMESTAMP(`1969T`) -- -31536000 (timestamp is before last epoch)
```

### FROM_UNIXTIME

Converts the given unix epoch into a timestamp.

Signature : `FROM_UNIXTIME: Integer|Decimal -> Timestamp`

Header : `FROM_UNIXTIME(unix_timestamp)`

Purpose : When given a non-negative numeric value, returns a timestamp after the last epoch.
When given a negative numeric value, returns a timestamp before the last epoch.
The returned timestamp has fractional seconds depending on if the value is a decimal.

Examples :
```sql
FROM_UNIXTIME(-1) -- `1969-12-31T23:59:59-00:00` (negative unix_timestamp; returns timestamp before last epoch)
FROM_UNIXTIME(-0.1) -- `1969-12-31T23:59:59.9-00:00` (unix_timestamp is decimal so timestamp has fractional seconds)
FROM_UNIXTIME(0) -- `1970-01-01T00:00:00.000-00:00`
FROM_UNIXTIME(0.001) -- `1970-01-01T00:00:00.001-00:00` (decimal precision to fractional second precision)
FROM_UNIXTIME(0.01) -- `1970-01-01T00:00:00.01-00:00`
FROM_UNIXTIME(0.1) -- `1970-01-01T00:00:00.1-00:00`
FROM_UNIXTIME(1) -- `1970-01-01T00:00:01-00:00`
FROM_UNIXTIME(1577836800) -- `2020-01-01T00:00:00-00:00` (unix_timestamp is Integer so no fractional seconds)
```
11 changes: 4 additions & 7 deletions lang/src/org/partiql/lang/eval/builtins/FromUnixTimeFunction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ import java.math.BigDecimal
* Syntax: `FROM_UNIXTIME(unix_timestamp)`
* Where unix_timestamp is a non-negative (potentially decimal) numeric value.
*
* When given a negative numeric value, this function returns a PartiQL `NULL` [ExprValue].
* When given a non-negative numeric value, this function returns a PartiQL `TIMESTAMP` [ExprValue] that has fractional
* seconds depending on if the value is a decimal.
* When given a negative numeric value, this function returns a PartiQL `TIMESTAMP` [ExprValue] before the last epoch.
* When given a non-negative numeric value, this function returns a PartiQL `TIMESTAMP` [ExprValue] after the last
* epoch.
* The returned `TIMESTAMP` has fractional seconds depending on if the value is a decimal.
*/
internal class FromUnixTimeFunction(valueFactory: ExprValueFactory) : NullPropagatingExprFunction("from_unixtime", 1, valueFactory) {
private val millisPerSecond = BigDecimal(1000)
Expand All @@ -27,10 +28,6 @@ internal class FromUnixTimeFunction(valueFactory: ExprValueFactory) : NullPropag

val numMillis = unixTimestamp.times(millisPerSecond).stripTrailingZeros()

if (unixTimestamp < BigDecimal.ZERO) {
return valueFactory.nullValue
}

val timestamp = Timestamp.forMillis(numMillis, null)
return valueFactory.newTimestamp(timestamp)
}
Expand Down
13 changes: 4 additions & 9 deletions lang/src/org/partiql/lang/eval/builtins/UnixTimestampFunction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ import java.math.BigDecimal
* '1970-01-01 00:00:00' UTC as a PartiQL `INT` [ExprValue]
*
* If UNIX_TIMESTAMP() is called with a [timestamp] argument, it returns the number of seconds from
* '1970-01-01 00:00:00' UTC to the given [timestamp] argument. The return value will be a decimal if and only if
* the given [timestamp] has a fractional seconds part.
* '1970-01-01 00:00:00' UTC to the given [timestamp] argument. If given a [timestamp] before the last epoch, will
* return the number of seconds before the last epoch as a negative number. The return value will be a decimal if and
* only if the given [timestamp] has a fractional seconds part.
*
* The valid range of argument values is from '1970-01-01 00:00:01.000000' UTC up to the maximum PartiQL `TIMESTAMP`
* value. If given a [timestamp] out of this range, UNIX_TIMESTAMP() will return 0.
* The valid range of argument values is the range of PartiQL's `TIMESTAMP` value.
*/
internal class UnixTimestampFunction(valueFactory: ExprValueFactory) : NullPropagatingExprFunction("unix_timestamp", 0..1, valueFactory) {
private val millisPerSecond = BigDecimal(1000)
Expand All @@ -34,11 +34,6 @@ internal class UnixTimestampFunction(valueFactory: ExprValueFactory) : NullPropa
}

val numMillis = timestamp.decimalMillis

if (numMillis < BigDecimal.ZERO) {
return valueFactory.newInt(0)
}

val epochTime = numMillis.divide(millisPerSecond)

if (timestamp.decimalSecond.scale() == 0 || args.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ class FromUnixTimeFunctionTest : EvaluatorTestBase() {

class FromUnixTimeTests : ArgumentsProviderBase() {
override fun getParameters(): List<Any> = listOf(
// negative unix epochs output null
FromUnixTimeTestCase("from_unixtime(-1)", "null"),
FromUnixTimeTestCase("from_unixtime(-0.1)", "null"),
// non-negative cases outputting a timestamp
// negative unix epochs output timestamp before last epoch
FromUnixTimeTestCase("from_unixtime(-1)", "1969-12-31T23:59:59-00:00"),
FromUnixTimeTestCase("from_unixtime(-0.1)", "1969-12-31T23:59:59.9-00:00"),
// non-negative cases outputting a timestamp after last epoch
FromUnixTimeTestCase("from_unixtime(0)", "1970-01-01T00:00:00.000-00:00"),
FromUnixTimeTestCase("from_unixtime(0.001)", "1970-01-01T00:00:00.001-00:00"),
FromUnixTimeTestCase("from_unixtime(0.01)", "1970-01-01T00:00:00.01-00:00"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ class UnixTimestampFunctionTest : EvaluatorTestBase() {

override fun getParameters(): List<Any> = listOf(
// time before the last epoch
UnixTimestampOneArgTestCase("unix_timestamp(`1969T`)", "0"),
UnixTimestampOneArgTestCase("unix_timestamp(`1969-12-31T23:59:59.999Z`)", "0"),
UnixTimestampOneArgTestCase("unix_timestamp(`1969T`)", "-31536000"),
UnixTimestampOneArgTestCase("unix_timestamp(`1969-12-31T23:59:59.999Z`)", "-0.001"),
// exactly the last epoch
UnixTimestampOneArgTestCase("unix_timestamp(`1970T`)", "0"),
UnixTimestampOneArgTestCase("unix_timestamp(`1970-01-01T00:00:00.000Z`)", "0."),
Expand Down

0 comments on commit 550121f

Please sign in to comment.