mulesoft-labs / data-weave-rfc

RFC for the data weave language
13 stars 5 forks source link

New module call dw::core::Dates #20

Open machaval opened 4 years ago

machaval commented 4 years ago

Continue with the #17 here we are bringing a new module dw::core::Dates This module introduce factory methods for all Date types (Date, DateTime, Time..) We also are introducing helper function for scheduling.

== dw::core::Dates

%dw 2.0

import * from dw::core::Periods
import failIf from dw::Runtime

/**
* Returns the Date for today.
*
*  _Introduced in DataWeave 2.3.1. Supported by Mule 4.3.1 and later._
*
* === Example
*
* This example shows the output of `today` function.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
* today()
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
* "2020-10-06"
* ----
**/
@Since(version = "2.3.1")
fun today() = now() as Date

/**
* Returns the Date for yesterday.
*
*  _Introduced in DataWeave 2.3.1. Supported by Mule 4.3.1 and later._
*
* === Example
*
* This example shows the output of `today` function.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
* yesterday()
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
* "2020-10-05"
* ----
**/
@Since(version = "2.3.1")
fun yesterday() = today() - days(1)

/**
* Returns the Date for tomorrow.
*
*  _Introduced in DataWeave 2.3.1. Supported by Mule 4.3.1 and later._
*
* === Example
*
* This example shows the output of `tomorrow` function.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
* tomorrow()
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
* "2020-10-07"
* ----
**/
@Since(version = "2.3.1")
fun tomorrow() = today() + days(1)

type Zoned = {timeZone: TimeZone}

type DateFactory =  {day: Number, month: Number, year: Number}

type LocalTimeFactory =  {hour: Number, minutes: Number, seconds: Number}

type TimeFactory = LocalTimeFactory & Zoned

type DateTimeFactory = DateFactory & LocalTimeFactory & Zoned

type LocalDateTimeFactory = DateFactory & LocalTimeFactory

/**
* Creates a Date value with the given date properties (year, month, day).
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | parts | The date fields
* |===
*
* === Example
*
* This example shows how to create a value of type Date
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
*  %dw 2.0
*  output application/json
*  import * from dw::core::Dates
*  ---
*  {
*     newDate: date({year: 2012, month: 10, day: 11})
*  }
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
*  {
*     "newDate": "2012-10-11"
*  }
* ----
**/
fun date(parts: DateFactory): Date = do {
    var nYear = parts.year as String
    var nMonth = failIf( parts.month , (month) -> month < 0 or month > 13, "Field 'month': `$(parts.month)` must be between 1 and 12.") as String
    var nDay = failIf( parts.day, (day) -> day < 0 or day > 31, "Field 'day': `$(parts.day)` must be between 1 and 31.") as String
    ---
    "$(nYear)-$(nMonth)-$(nDay)" as Date
}

/**
* Creates a DateTime value with the given datetime properties (year, month, day, hour, minutes, seconds and timeZone).
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | parts | The date fields
* |===
*
* === Example
*
* This example shows how to create a value of type DateTime
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
*  %dw 2.0
*  output application/json
*  import * from dw::core::Dates
*  ---
*  {
*      newDateTime: dateTime({year: 2012, month: 10, day: 11, hour: 10, minutes: 10, seconds: 10 , timeZone: |-03:00|})
*  }
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
*  {
*     "newDateTime": "2012-10-11T10:10:10-03:00",
*  }
* ----
**/
fun dateTime(parts: DateTimeFactory): DateTime = do {
     var nYear = parts.year as String
     var nMonth = failIf( parts.month , (month) -> month < 0 or month > 12, "Field 'month': `$(parts.month)` must be between 1 and 12.") as String
     var nDay = failIf( parts.day, (day) -> day < 0 or day > 31, "Field 'day': `$(parts.day)` must be between 1 and 31.") as String
     var nHours = failIf( parts.hour, (hour) -> hour < 0 or hour > 24, "Field 'hours': `$(parts.hour)` must be between 0 and 24.") as String
     var nMinutes = failIf( parts.minutes, (minutes) -> minutes < 0 or minutes > 60, "Field 'minutes': `$(parts.minutes)` must be between 0 and 60.") as String
     ---
     "$(nYear)-$(nMonth)-$(nDay)T$(nHours):$(nMinutes):$(parts.seconds as String)$(parts.timeZone as String)" as DateTime
}

/**
* Creates a LocalDateTime value with the given localDatetime properties (year, month, day, hour, minutes, seconds).
*
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | parts | The localDateTime fields
* |===
*
* === Example
*
* This example shows how to create a value of type DateTime
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
*  %dw 2.0
*  output application/json
*  import * from dw::core::Dates
*  ---
*  {
*      newLocalDateTime: localDateTime({year: 2012, month: 10, day: 11, hour: 10, minutes: 10, seconds: 10})
*  }
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
*  {
*     "newLocalDateTime": "2012-10-11T10:10:10",
*  }
* ----
**/
fun localDateTime(parts: LocalDateTimeFactory): LocalDateTime = do {
    var nYear = parts.year as String
    var nMonth = failIf( parts.month , (month) -> month < 0 and month > 12, "Field 'month': `$(parts.month)` must be between 1 and 12.") as String
    var nDay = failIf( parts.day, (day) -> day < 0 and day > 31, "Field 'day': `$(parts.day)` must be between 1 and 31.") as String
    var nHours = failIf( parts.hour, (hour) -> hour < 0 and hour > 24, "Field 'hours': `$(parts.hour)` must be between 0 and 24.") as String
    var nMinutes = failIf( parts.minutes, (minutes) -> minutes < 0 and minutes > 60, "Field 'minutes': `$(parts.minutes)` must be between 0 and 60.") as String
    ---
    "$(nYear)-$(nMonth)-$(nDay)T$(nHours):$(nMinutes):$(parts.seconds as String)" as LocalDateTime
}

/**
* Creates a LocalTime value with the given localtime  properties (hour, minutes, seconds).
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | parts | The localTime fields
* |===
*
* === Example
*
* This example shows how to create a value of type LocalTime
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
*  %dw 2.0
*  output application/json
*  import * from dw::core::Dates
*  ---
*  {
*    newLocalTime: localTime({ hour: 10, minutes: 10, seconds: 10}),
*  }
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
*  {
*     "newLocalTime": "10:10:10"
*  }
* ----
**/
fun localTime(parts: LocalTimeFactory): LocalTime = do {
    var nHours = failIf( parts.hour, (hour) -> hour < 0 and hour > 24, "Field 'hours': `$(parts.hour)` must be between 0 and 24.") as String
    var nMinutes = failIf( parts.minutes, (minutes) -> minutes < 0 and minutes > 60, "Field 'minutes': `$(parts.minutes)` must be between 0 and 60.") as String
    ---
    "$(nHours):$(nMinutes):$(parts.seconds as String)" as LocalTime
}

/**
* Creates a Time value with the given time  properties (hour, minutes, seconds and timeZone).
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | parts | The time fields
* |===
*
* === Example
*
* This example shows how to create a value of type Time
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
*  %dw 2.0
*  output application/json
*  import * from dw::core::Dates
*  ---
*  {
*    newTime: time({ hour: 10, minutes: 10, seconds: 10 , timeZone: |-03:00|}),
*  }
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
*  {
*     "newTime": "10:10:10-03:00"
*  }
* ----
**/
fun time(parts: TimeFactory): Time =do {
    var nHours = failIf( parts.hour, (hour) -> hour < 0 and hour > 24, "Field 'hours': `$(parts.hour)` must be between 0 and 24.") as String
    var nMinutes = failIf( parts.minutes, (minutes) -> minutes < 0 and minutes > 60, "Field 'minutes': `$(parts.minutes)` must be between 0 and 60.") as String
    ---
    "$(nHours):$(nMinutes):$(parts.seconds as String)$(parts.timeZone as String)" as Time
}

/**
* Returns a new DateTime with the Time changed to the start of the current hour
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | dateTime | The DateTime used as reference
* |===
*
* === Example
*
* This shows how it changes the specified Time to the the start of the given hour.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
*  {
*     "atBeginningOfHour": atBeginningOfHour(|2020-10-06T18:23:20.351-03:00|)
*  }
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
*  {
*   "atBeginningOfHour": "2020-10-06T18:00:00-03:00"
*  }
* ----
**/
fun atBeginningOfHour(dateTime: DateTime): DateTime =
  "$(dateTime as Date as String)T$(dateTime.hour as String):00:00.000$(dateTime.timezone as String)" as DateTime

/**
*Returns a new LocalDateTime changed to the beginning of the given hour
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | localDateTime | The LocalDateTime used as reference
* |===
*
* === Example
*
* This shows how it changes the specified Time to the the start of the given hour.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
*  {
*     "atBeginningOfHour": atBeginningOfHour(|2020-10-06T18:23:20.351|)
*  }
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
*  {
*   "atBeginningOfHour": "2020-10-06T18:00:00"
*  }
* ----
**/
fun atBeginningOfHour(localDateTime: LocalDateTime): LocalDateTime =
  "$(localDateTime as Date as String)T$(localDateTime.hour as String):00:00.000" as LocalDateTime

/**
* Returns a new LocalTime changed to the start of the current hour
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | dateTime |
* |===
*
* === Example
*
* This shows how it changes the specified LocalTime to the the start of the given hour.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
*  {
*     "atBeginningOfHour": atBeginningOfHour(|18:23:20.351|)
*  }
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
*  {
*   "atBeginningOfHour": "18:00:00"
*  }
* ----
**/
fun atBeginningOfHour(localTime: LocalTime): LocalTime =
  "$(localTime.hour as String):00:00.000" as LocalTime

/**
* Returns a new Time changed to the beginning of the given hour.
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | time | The time to be used as reference
* |===
*
* === Example
*
* This shows how it changes the specified Time to the the start of the given hour.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
*  {
*     "atBeginningOfHour": atBeginningOfHour(|18:23:20.351-03:00|)
*  }
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
*  {
*   "atBeginningOfHour":  "18:00:00-03:00"
*  }
* ----
**/
fun atBeginningOfHour(time: Time): Time =
  "$(time.hour as String):00:00.000$(time.timezone as String)" as Time

/**
* Returns a new DateTime but at the beginning of the day of the given DateTime
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | dateTime | The dateTime to be used as reference
* |===
*
* === Example
*
* This example shows how it transforms the DateTime `2020-10-06T18:23:20.351-03:00` to the same date but at the start of the given day.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
* {
*   "atBeginningOfDayDateTime": atBeginningOfDay(|2020-10-06T18:23:20.351-03:00|)
* }
*
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
* {
*   "atBeginningOfDayDateTime": "2020-10-06T00:00:00-03:00"
* }
* ----
**/
fun atBeginningOfDay(dateTime: DateTime): DateTime =
  "$(dateTime as Date as String)T00:00:00.000$(dateTime.timezone as String)" as DateTime

/**
* Returns a new LocalDateTime but at the beginning of the day of the given LocalDateTime
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | dateTime | The dateTime to be used as reference
* |===
*
* === Example
*
* This example shows how it transforms the LocalDateTime `2020-10-06T18:23:20.351-03:00` to the same date but at the start of the given day.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
* {
*   "atBeginningOfDayLocalDateTime": atBeginningOfDay(|2020-10-06T18:23:20.351|)
* }
*
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
* {
*   "atBeginningOfDayLocalDateTime": "2020-10-06T00:00:00"
* }
* ----
**/
fun atBeginningOfDay(dateTime: LocalDateTime): LocalDateTime =
  "$(dateTime as Date as String)T00:00:00.000" as LocalDateTime

/**
* Returns a new DateTime but at the beginning of the Month of the given DateTime
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | dateTime | The dateTime to be used as reference
* |===
*
* === Example
*
* This example shows how it transforms the DateTime `2020-10-06T18:23:20.351-03:00` to the same date but at the start of the given Month.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
* {
*   atBeginningOfMonth(|2020-10-06T18:23:20.351-03:00|)
* }
*
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
* {
*   "atBeginningOfMonth": "2020-10-01T00:00:00-03:00"
* }
* ----
**/
fun atBeginningOfMonth(dateTime: DateTime): DateTime =
  "$((dateTime as Date - days(dateTime.day - 1)) as String)T00:00:00.000$(dateTime.timezone as String)" as DateTime

/**
* Returns a new LocalDateTime but at the beginning of the Month of the given LocalDateTime
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | dateTime | The localDateTime to be used as reference
* |===
*
* === Example
*
* This example shows how it transforms the LocalDateTime `2020-10-06T18:23:20.351` to the same date but at the start of the given Month.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
* {
*  "atBeginningOfMonth": atBeginningOfMonth(|2020-10-06T18:23:20.351|)
* }
*
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
* {
*   "atBeginningOfMonth": "2020-10-01T00:00:00"
* }
* ----
**/
fun atBeginningOfMonth(localDateTime: LocalDateTime): LocalDateTime =
   "$((localDateTime as Date - days(localDateTime.day - 1)) as String)T00:00:00.000" as LocalDateTime

/**
* Returns a new Date but at the beginning of the Month of the given Date
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | dateTime | The date to be used as reference
* |===
*
* === Example
*
* This example shows how it transforms the Date |2020-10-06| to the same date but at the start of the given Month.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
* {
*   atBeginningOfMonthDate: atBeginningOfMonth(|2020-10-06|)
* }
*
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
* {
*   "atBeginningOfMonth": "2020-10-01"
* }
* ----
**/
fun atBeginningOfMonth(date: Date): Date =
    "$((date - days(date.day - 1)) as String)" as Date

/**
* Returns a new DateTime but at the beginning of the Week of the given DateTime
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | dateTime | The dateTime to be used as reference
* |===
*
* === Example
*
* This example shows how it transforms the DateTime |2020-10-06T18:23:20.351-03:00| to the same date but at the start of the given Week.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
* {
*   atBeginningOfWeekDateTime: atBeginningOfWeek(|2020-10-06T18:23:20.351-03:00|)
* }
*
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
* {
*   "atBeginningOfMonth": "2020-10-04T00:00:00-03:00"
* }
* ----
**/
fun atBeginningOfWeek(dateTime: DateTime): DateTime =
  "$((dateTime as Date - days(dateTime.dayOfWeek)) as String)T00:00:00.000$(dateTime.timezone as String)" as DateTime

/**
* Returns a new LocalDateTime but at the beginning of the Week of the given LocalDateTime
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | localDateTime | The localDateTime to be used as reference
* |===
*
* === Example
*
* This example shows how it transforms the LocalDateTime |2020-10-06T18:23:20.351| to the same date but at the start of the given Week.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
* {
*   atBeginningOfMonth: atBeginningOfWeek(|2020-10-06T18:23:20.351|)
* }
*
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
* {
*   "atBeginningOfMonth": "2020-10-04T00:00:00"
* }
* ----
**/
fun atBeginningOfWeek(localDateTime: LocalDateTime): LocalDateTime =
  "$((localDateTime as Date - days(localDateTime.dayOfWeek)) as String)T00:00:00.000" as LocalDateTime

/**
* Returns a new Date but at the beginning of the Week of the given Date
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | date | The date to be used as reference
* |===
*
* === Example
*
* This example shows how it transforms the Date |2020-10-06| to the same date but at the start of the given Week.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
* {
*   atBeginningOfMonth: atBeginningOfWeek(|2020-10-06|)
* }
*
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
* {
*   "atBeginningOfMonth": "2020-10-04"
* }
* ----
**/
fun atBeginningOfWeek(date: Date): Date =
  "$((date - days(date.dayOfWeek)) as String)" as Date

/**
* Returns a new DateTime but at the beginning of the Year of the given DateTime
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | dateTime | The dateTime to be used as reference
* |===
*
* === Example
*
* This example shows how it transforms the DateTime |2020-10-06T18:23:20.351-03:00| to the same date but at the start of the given Year.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
* {
*   atBeginningOfYear: atBeginningOfYear(|2020-10-06T18:23:20.351-03:00|)
* }
*
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
* {
*   "atBeginningOfYear": "2020-01-01T00:00:00.000-03:00"
* }
* ----
**/
fun atBeginningOfYear(dateTime: DateTime): DateTime =
  "$((dateTime as Date - days(dateTime.dayOfYear - 1)) as String)T00:00:00.000$(dateTime.timezone as String)" as DateTime

/**
* Returns a new LocalDateTime but at the beginning of the Year of the given LocalDateTime
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | localDateTime | The localDateTime to be used as reference
* |===
*
* === Example
*
* This example shows how it transforms the LocalDateTime |2020-10-06T18:23:20.351| to the same date but at the start of the given Year.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
* {
*   atBeginningOfYear: atBeginningOfYear(|2020-10-06T18:23:20.351|)
* }
*
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
* {
*   "atBeginningOfYear": "2020-01-01T00:00:00.000"
* }
* ----
**/
fun atBeginningOfYear(localDateTime: LocalDateTime): LocalDateTime =
  "$((localDateTime as Date - days(localDateTime.dayOfYear - 1)) as String)T00:00:00.000" as LocalDateTime

/**
* Returns a new Date but at the beginning of the Year of the given Date
*
* === Parameters
*
* [%header, cols="1,3"]
* |===
* | Name   | Description
* | date | The date to be used as reference
* |===
*
* === Example
*
* This example shows how it transforms the Date |2020-10-06| to the same date but at the start of the given Year.
*
* ==== Source
*
* [source,DataWeave,linenums]
* ----
* %dw 2.0
* output application/json
* ---
* {
*   atBeginningOfYear: atBeginningOfYear(|2020-10-06|)
* }
*
* ----
*
* ==== Output
*
* [source,Json,linenums]
* ----
* {
*   "atBeginningOfYear": "2020-01-01"
* }
* ----
**/
fun atBeginningOfYear(date: Date): Date =
  "$((date as Date - days(date.dayOfYear - 1)) as String)" as Date

Feedback on method names and missing functionality that would be interesting to have here