Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ class PgDateSupportJodaSuite extends AnyFunSuite with PostgresContainer {
Datetimes.filter(_.id === 101L.bind).map(r => r.datetime.trunc("day")).result.head.map(
r => assert(LocalDateTime.parse("2001-01-03T00:00:00") === r)
),
// dateBin
DBIO.seq(Option.when(pgVersion.take(2).toInt >= 14)(Datetimes.filter(_.id === 101L.bind).map(r => r.datetime.dateBin("1 hour", LocalDateTime.parse("2001-01-03T18:35:17"))).result.head.map(
Copy link
Copy Markdown
Contributor Author

@hughsimpson hughsimpson Jun 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The gnarly little wrapper here (and elsewhere) could be refactored out for a more principled approach to supporting features that're only introduced in later versions of postgres, but I figured I'd test the waters first, and don't currently need any other feature missing from the existing set

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't matter, I think, since it's postgresql that really supports these functions, instead of slick-pg.
In fact, slick-pg is just a tool that translates from scala functions to pg functions.

r => assert(LocalDateTime.parse("2001-01-03T12:35:17") === r)
)).toSeq:_*),
// isFinite
Datetimes.filter(_.id === 101L.bind).map(r => r.datetime.isFinite).result.head.map(
r => assert(true === r)
Expand Down Expand Up @@ -204,7 +208,11 @@ class PgDateSupportJodaSuite extends AnyFunSuite with PostgresContainer {
// trunc
Datetimes.filter(_.id === 101L.bind).map(r => r.datetimetz.trunc("day")).result.head.map(
r => assert(DateTime.parse("2001-01-03 00:00:00.000+08", jodaTzDateTimeFormatter) === r)
)
),
// dateBin
DBIO.seq(Option.when(pgVersion.take(2).toInt >= 14)(Datetimes.filter(_.id === 101L.bind).map(r => r.datetimetz.dateBin("1 hour", DateTime.parse("2001-01-02T18:35:17+08"))).result.head.map(
r => assert(DateTime.parse("2001-01-03 12:35:17.000+08", jodaTzDateTimeFormatter) === r)
)).toSeq:_*)
),
// update and check
DBIO.seq(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ trait PgDateExtensions extends JdbcTypesComponent { driver: PostgresProfile =>
val Age = new SqlFunction("age")
val Part = new SqlFunction("date_part")
val Trunc = new SqlFunction("date_trunc")
val DateBin = new SqlFunction("date_bin")
val IsFinite = new SqlFunction("isfinite")

val JustifyDays = new SqlFunction("justify_days")
Expand Down Expand Up @@ -65,6 +66,9 @@ trait PgDateExtensions extends JdbcTypesComponent { driver: PostgresProfile =>
def trunc[R](field: Rep[String])(implicit om: o#to[TIMESTAMP, R]) = {
om.column(DateLibrary.Trunc, field.toNode, n)
}
def dateBin[R](step: Rep[String], base: Rep[TIMESTAMP])(implicit om: o#to[TIMESTAMP, R]) = {
om.column(DateLibrary.DateBin, step.toNode, n, base.toNode)
}
def isFinite[R](implicit om: o#to[Boolean, R]) = om.column(DateLibrary.IsFinite, n)

def atTimeZone[R](tz: Rep[String])(implicit om: o#to[TIMESTAMP_TZ, R]) =
Expand Down
51 changes: 26 additions & 25 deletions core/src/main/scala/com/github/tminglei/slickpg/date/README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
Supported Date/Time Oper/Functions
---------------------------------

| Slick Oper/Function | PG Oper/Function | Description | Example | Result |
| ------------------- | ---------------- | ----------------------- | ---------------------------------------------- | ------------------------ |
| +++ | + | timestamp + interval | timestamp '2001-09-28 01:00' + interval '23 hours'|timestamp '2001-09-29 00:00:00'|
| - | - | timestamp - timestamp | timestamp '2001-09-29 03:00' - timestamp '2001-09-27 12:00'|interval '1 day 15:00:00'|
| -- | - | timestamp - time | timestamp '2001-09-29 03:00' - time '03:00' | timestamp '2001-09-29 00:00'|
| --- | - | timestame - interval | timestamp '2001-09-28 23:00' - interval '23 hours'|timestamp '2001-09-28 00:00:00'|
| age | age | age(timestamp[, timestamp])| age(timestamp '2001-04-10', timestamp '1957-06-13')|43 years 9 mons 27 days|
| age | age | age(timestamp) | age(timestamp '1957-06-13') | 43 years 9 mons 27 days |
| part | date_part/extract| date_part(text, timestamp) | date_part('hour', timestamp '2001-02-16 20:38:40') | 20 |
| trunc | date_trunc | date_trunc(text, timestamp)| date_trunc('hour', timestamp '2001-02-16 20:38:40') | 2001-02-16 20:00:00 |
| + | + | date + time | date '2001-09-28' + time '03:00' | timestamp '2001-09-28 03:00:00' |
| ++ | + | date + int | date '2001-10-01' - integer '7' | date '2001-09-24' |
| +++ | + | date + interval | date '2001-09-28' + interval '1 hour' | timestamp '2001-09-28 01:00:00' |
| - | - | date - date | date '2001-10-01' - date '2001-09-28' | integer '3' (days) |
| -- | - | date - int | date '2001-10-01' - integer '7' | date '2001-09-24' |
| --- | - | date - interval | date '2001-09-28' - interval '1 hour' | timestamp '2001-09-27 23:00:00' |
| + | + | time + date | time '03:00' + date '2001-09-28' | timestamp '2001-09-28 03:00:00' |
| +++ | + | time + interval | time '05:00' - interval '2 hours' | time '03:00:00' |
| - | - | time - time | time '05:00' - time '03:00' | interval '02:00:00' |
| --- | - | time - interval | time '05:00' - interval '2 hours' | time '03:00:00' |
| + | + | interval + interval | interval '1 day' + interval '1 hour' | interval '1 day 01:00:00' |
| unary_- | - | - interval | - interval '23 hours' | interval '-23:00:00' |
| - | - | interval - interval | interval '1 day' - interval '1 hour' | interval '1 day -01:00:00' |
| * | * | interval * factor | double precision '3.5' * interval '1 hour'| interval '03:30:00' |
| / | / | interval / factor | interval '1 hour' / double precision '1.5'| interval '00:40:00' |
| Slick Oper/Function | PG Oper/Function | Description | Example | Result |
|---------------------|-------------------|--------------------------------------|--------------------------------------------------------------------------------------|---------------------------------|
| +++ | + | timestamp + interval | timestamp '2001-09-28 01:00' + interval '23 hours' | timestamp '2001-09-29 00:00:00' |
| - | - | timestamp - timestamp | timestamp '2001-09-29 03:00' - timestamp '2001-09-27 12:00' | interval '1 day 15:00:00' |
| -- | - | timestamp - time | timestamp '2001-09-29 03:00' - time '03:00' | timestamp '2001-09-29 00:00' |
| --- | - | timestame - interval | timestamp '2001-09-28 23:00' - interval '23 hours' | timestamp '2001-09-28 00:00:00' |
| age | age | age(timestamp[, timestamp]) | age(timestamp '2001-04-10', timestamp '1957-06-13') | 43 years 9 mons 27 days |
| age | age | age(timestamp) | age(timestamp '1957-06-13') | 43 years 9 mons 27 days |
| part | date_part/extract | date_part(text, timestamp) | date_part('hour', timestamp '2001-02-16 20:38:40') | 20 |
| trunc | date_trunc | date_trunc(text, timestamp) | date_trunc('hour', timestamp '2001-02-16 20:38:40') | 2001-02-16 20:00:00 |
| dateBin | date_bin | date_bin(text, timestamp, timestamp) | date_bin('1 hour', timestamp '2001-02-16 20:38:40', timestamp '2001-02-16 18:35:17') | 2001-02-16 20:35:17 |
| + | + | date + time | date '2001-09-28' + time '03:00' | timestamp '2001-09-28 03:00:00' |
| ++ | + | date + int | date '2001-10-01' - integer '7' | date '2001-09-24' |
| +++ | + | date + interval | date '2001-09-28' + interval '1 hour' | timestamp '2001-09-28 01:00:00' |
| - | - | date - date | date '2001-10-01' - date '2001-09-28' | integer '3' (days) |
| -- | - | date - int | date '2001-10-01' - integer '7' | date '2001-09-24' |
| --- | - | date - interval | date '2001-09-28' - interval '1 hour' | timestamp '2001-09-27 23:00:00' |
| + | + | time + date | time '03:00' + date '2001-09-28' | timestamp '2001-09-28 03:00:00' |
| +++ | + | time + interval | time '05:00' - interval '2 hours' | time '03:00:00' |
| - | - | time - time | time '05:00' - time '03:00' | interval '02:00:00' |
| --- | - | time - interval | time '05:00' - interval '2 hours' | time '03:00:00' |
| + | + | interval + interval | interval '1 day' + interval '1 hour' | interval '1 day 01:00:00' |
| unary_- | - | - interval | - interval '23 hours' | interval '-23:00:00' |
| - | - | interval - interval | interval '1 day' - interval '1 hour' | interval '1 day -01:00:00' |
| * | * | interval * factor | double precision '3.5' * interval '1 hour' | interval '03:30:00' |
| / | / | interval / factor | interval '1 hour' / double precision '1.5' | interval '00:40:00' |
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ class PgDate2SupportSuite extends AnyFunSuite with PostgresContainer {
Datetimes.filter(_.id === 101L.bind).map(r => r.dateTime.trunc("day")).result.head.map(
r => assert(LocalDateTime.parse("2001-01-03T00:00:00") === r)
),
// dateBin
DBIO.seq(Option.when(pgVersion.take(2).toInt >= 14)(Datetimes.filter(_.id === 101L.bind).map(r => r.dateTime.dateBin("1 hour", LocalDateTime.parse("2001-01-03T18:35:17"))).result.head.map(
r => assert(LocalDateTime.parse("2001-01-03T12:35:17") === r)
)).toSeq:_*),
// isFinite
Datetimes.filter(_.id === 101L.bind).map(r => r.dateTime.isFinite).result.head.map(
r => assert(true === r)
Expand Down Expand Up @@ -223,7 +227,11 @@ class PgDate2SupportSuite extends AnyFunSuite with PostgresContainer {
),
Datetimes.filter(_.id === 101L.bind).map(r => r.dateTimeTz.trunc("day")).result.head.map(
r => assert(ZonedDateTime.parse("2001-01-03 00:00:00+08", date2TzDateTimeFormatter) === r)
)
),
// dateBin
DBIO.seq(Option.when(pgVersion.take(2).toInt >= 14)(Datetimes.filter(_.id === 101L.bind).map(r => r.dateTimeTz.dateBin("1 hour", ZonedDateTime.parse("2001-01-03 18:35:17+03", date2TzDateTimeFormatter))).result.head.map(
r => assert(ZonedDateTime.parse("2001-01-03 12:35:17+08", date2TzDateTimeFormatter) === r)
)).toSeq:_*)
),
// Timezones
Datetimes.filter(_.id === 101L.bind).map(r => r.zone).result.head.map(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import scala.concurrent.Await
import scala.concurrent.duration._

class PgDateSupportSuite extends AnyFunSuite with PostgresContainer {

import MyPostgresProfile.api._

lazy val db = Database.forURL(url = container.jdbcUrl, driver = "org.postgresql.Driver")
Expand Down Expand Up @@ -143,6 +144,10 @@ class PgDateSupportSuite extends AnyFunSuite with PostgresContainer {
Datetimes.filter(_.id === 101L.bind).map(r => r.timestamp.trunc("day")).result.head.map(
r => assert(ts("2001-1-3 00:00:00.0").toLocalDateTime === r.toLocalDateTime)
),
// dateBin
DBIO.seq(Option.when(pgVersion.take(2).toInt >= 14)(Datetimes.filter(_.id === 101L.bind).map(r => r.timestamp.dateBin("1 hour", ts("2001-1-3 18:35:17"))).result.head.map(
r => assert(ts("2001-01-03 12:35:17").toLocalDateTime === r.toLocalDateTime)
)).toSeq: _*),
// isFinite
Datetimes.filter(_.id === 101L.bind).map(r => r.timestamp.isFinite).result.head.map(
r => assert(true === r)
Expand Down Expand Up @@ -202,7 +207,11 @@ class PgDateSupportSuite extends AnyFunSuite with PostgresContainer {
// trunc
Datetimes.filter(_.id === 101L.bind).map(r => r.timestamptz.trunc("day")).result.head.map(
r => assert(tstz("2001-01-03T00:00:00+08:00").getTimeInMillis === r.getTimeInMillis)
)
),
// dateBin
DBIO.seq(Option.when(pgVersion.take(2).toInt >= 14)(Datetimes.filter(_.id === 101L.bind).map(r => r.timestamptz.dateBin("1 hour", tstz("2001-01-02T18:35:17+03"))).result.head.map(
r => assert(tstz("2001-01-03T12:35:17+08").getTimeInMillis === r.getTimeInMillis)
)).toSeq: _*)
)
)
).andFinally(
Expand Down