mulesoft-labs / data-weave-rfc

RFC for the data weave language
11 stars 6 forks source link

Date utilities module #17

Open adobni opened 4 years ago

adobni commented 4 years ago

It could be useful to have a date module, with common operations that are used in businesses, like days in a month, and epoch time conversion to date/time.

machaval commented 4 years ago

For epoch we have :

To Epoc

%dw 2.0
output application/json
---
now() as Number {unit: "seconds"}

From Epoc

%dw 2.0
output application/json
---
1592601210 as DateTime {unit: "seconds"}

Days in a month is tricky as it may depend in the year (We all like feb)

But the other day a request came that we should be able to extract more information from timezeone

{
"displayName": "Eastern Standard Time",
"dstSavings": 3600000,
"id": "America/New_York",
"observesDaylightTime": true,
"rawOffset": -18000000,
"useDaylightTime": true
}

This kind of information. This may be interesting to analyze. Regarding date functions I think we also need Period factory methods.

Today if I want to substract a dynamic amount of days I need to use string interpolation and coercion.

now() - Period::days(1)
jerneyio commented 4 years ago

daysInMonth could be simple if you pass it a specific date:

daysInMonth(|2020-02-03|)
psmith commented 4 years ago

As Jerney said, days in month is easy, if you have a given date. A little weird, but I use something similar to get the first or last day of the month.

I wrote my own date module for stuff like this.

%dw 2.0
output application/json
fun lastDayOfMonth(d: Date) = d + |P1M| - ('P$(d.day as String)D') as Period
fun daysInMonth(d: Date) = lastDayOfMonth(d).day
---
{
    leapYearFeb: daysInMonth(|2020-02-13|),
    nonLeapYearFeb: daysInMonth(|2019-02-13|)
}

Results:

{
  "leapYearFeb": 29,
  "nonLeapYearFeb": 28
}
psmith commented 4 years ago

This kind of information. This may be interesting to analyze. Regarding date functions I think we also need Period factory methods.

Today if I want to substract a dynamic amount of days I need to use string interpolation and coercion.

now() - Period::days(1)

I love this idea, the string interpolation for dynamic periods is really annoying when you don't know how to do it. Easy, like most things, after you figure it out.

machaval commented 3 years ago

I'm going to separate this thing in two parts

  1. Is Convertions and Formating: Going from a Date to a number or a String and Back. I think we have a general problem with this that is not just for Dates
  2. Missing functionality arround dates. This issue is going to be about this. And a new one is going to be created for 1.
machaval commented 3 years ago

I propose one single module dw::core::Dates with all the functionality. This will make it simple to remember. One Module that will allow to do Date Arithmetic date manipulation.

%dw 2.0

fun today():Date =
  now() as Date

fun month(months: Number):Period =
  "P$(months)M" as Period

fun years(months: Number):Period =
  "P$(months)Y" as Period

fun days(nDays: Number):Period =
  "P$(nDays)D" as Period

fun hours(nHours: Number):Period =
  "PT$(nHours)H" as Period

fun minutes(nMinutes: Number):Period =
  "PT$(nMinutes)M" as Period

fun seconds(nSecs: Number):Period =
  "PT$(nSecs)S" as Period

fun toBeginningOfHour(dateTime: DateTime) =
  "$(dateTime as Date)T$(dateTime.hour):00:00.000$(dateTime.timezone)" as DateTime

fun toBeginningOfDay(dateTime: DateTime) =
  "$(dateTime as Date)T00:00:00.000$(dateTime.timezone)" as DateTime

fun toBeginningOfMonth(dateTime: DateTime) =
  "$(dateTime as Date - days(dateTime.day))T00:00:00.000$(dateTime.timezone)" as DateTime

fun toBeginningOfWeek(dateTime: DateTime) =
  "$(dateTime as Date - days(dateTime.dayOfWeek))T00:00:00.000$(dateTime.timezone)" as DateTime

fun toBeginningOfYear(dateTime: DateTime) =
  "$(dateTime as Date - days(dateTime.dayOfYear))T00:00:00.000$(dateTime.timezone)" as DateTime

Now we also have things like :

{
  "wday": now().dayOfWeek, //This will return 2
  "yday": |2020-09-29T16:11:12.195-03:00|.dayOfYear, // This return the day of the year for example 273 
}

The question is shouldn't this be functions? there are transformations in this selection. For me . should only be used for extracting data |2020-09-29T16:11:12.195-03:00|.year is ok because you are taking date out of the date but I don't see this on this examples.