Check if data is less than the previous month value in mule4 - mule4

My scenario is to check if the data value is less than the previous month date value.
Suppose current date is 2020-05-01 (YYYY-MM-DD)
and date value coming from the source is 2020-02-01 (YYYY-MM-DD)
I need to ignore this record and set flag value in mule4

Assuming the dates come as strings, you have to convert them to Dates with the right format pattern. Note that the right pattern is "yyyy-MM-dd". Once it is converted to a Date type then you can extract the desired part of the date.
I'm not really sure why you need only the month but note that if the year is significant the comparison will be meaningless. You could compare just the dates instead to take into account year, month and day.
Example:
Input:
{
"date1": "2020-05-01",
"date2": "2020-02-01"
}
Script:
%dw 2.0
output application/json
---
{
a: (payload.date1 as Date {format: "yyyy-MM-dd"}).month,
b: (payload.date2 as Date {format: "yyyy-MM-dd"}).month,
c: (payload.date1 as Date {format: "yyyy-MM-dd"}).month > (payload.date2 as Date {format: "yyyy-MM-dd"}).month
}
Output:
{
"a": 5,
"b": 2,
"c": true
}

Related

How to convert YearWeek format to date?

My data: c("202001", "202002").
It shows Year and the number of the week. I need to get the first day of the week added to my data.
How can I get it?
Desired output: 2020-01-06 and 2020-01-13.
Original data, for which the code should work
c(
"202001", "202002", "202003", "202004", "202005", "202006", "202007",
"202008", "202009", "202010", "202011", "202012", "202013", "202014",
"202015", "202016", "202017", "202018", "202019", "202020", "202021",
"202022", "202023", "202024", "202025", "202026", "202027", "202028",
"202029", "202030", "202031", "202032", "202033", "202034", "202035",
"202036", "202037", "202038", "202039", "202040", "202041", "202042",
"202043", "202044", "202045", "202046", "202047", "202048", "202049",
"202050", "202051", "202052", "202053", "202101", "202102", "202103")```
You can do this with base-r using as.Date and specifying the format.
Week of the year
US convention: Week of the year as decimal number (00–53) using Sunday as the first day 1 of the week (and typically with the first Sunday of the year as day 1 of week 1): %U
UK convention: Week of the year as decimal number (00–53) using Monday as the first day of week (and typically with the first Monday of the year as day 1 of week 1): %W
ISO 8601 definition: Week of the year as decimal number (01–53) as defined in ISO 8601. If the week (starting on Monday) containing 1 January has four or more days in the new year, then it is considered week 1. Otherwise, it is the last week of the previous year, and the next week is week 1: %V which is accepted but ignored on input.
Note that there is also a week-based year (%G and %g) which is to be used with %V as it may differ from the calendar year (%Y and %y).
Numeric weekday
Weekday as a decimal number (1–7, Monday is 1): %u
Weekday as decimal number (0–6, Sunday is 0): %w
I append 1 to create a date string referencing the first day of the year-week and then specify the format using strptime codes when calling as.date to convert it.
Example with US convention:
dateList <- c("202001", "202002")
dateList <- paste0(dateList, "1")
dateList <- as.Date(dateList , format = "%Y%W%u")
More information on the formats is available here:
https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/strptime
One way would be to use lubridate package like this:
c("202001", "202002") -> x
lubridate::ymd('2019-12-30') + lubridate::weeks(as.numeric(substr(x, 5, 6)))
#"2020-01-06" "2020-01-13"

How do I convert characters to a time that has fractional seconds without adding a date?

Is there a way to convert a string of characters to a time that retains the fractional seconds, but does not add a date to the data?
Background: Data that I saved overnight (starting at 22:00 and ending at 06:00) is recorded with a time, but not a date.
I would like to be able to perform something like an "if" statement on the times (i.e. if (time < midnight) date = yesterday.... else date = today)
I don't want to use something like strptime, because strptime adds today's date to the data:
> options(digits.secs=3)
> strptime("22:59:54.807", format="%H:%M:%OS")
[1] "2019-01-20 22:59:54.807 AEDT"
When I use times from the chron package, the fractional seconds are dropped:
> options(digits.secs=3)
> times("22:59:54.807")
[1] 22:59:55
Using base::strftime(), you can obtain a character of the desired time to any divide of seconds you want. Below I have saved the current time to unit 1/1000 of a second, using the number "4" after "OS":
Using current system time:
time = Sys.time()
str(time)
POSIXct[1:1], format: "2019-01-19 15:41:28.185"
newTime = strftime(Sys.time(), format="%H:%M:%OS4")
str(newTime)
chr "15:41:28.1851"
newTime
[1] "15:41:28.1851"

How to parse an invalid date with lubridate?

I need to parse dates and have a cases like "31/02/2018":
library(lubridate)
> dmy("31/02/2018", quiet = T)
[1] NA
This makes sense as the 31st of Feb does not exist. Is there a way to parse the string "31/02/2018" to e.g. 2018-02-28 ? So not to get an NA, but an actual date?
Thanks.
We can write a function assuming you would only have dates which could be higher than the actual date and would have the same format always.
library(lubridate)
get_correct_date <- function(example_date) {
#Split vector on "/" and get 3 components (date, month, year)
vecs <- as.numeric(strsplit(example_date, "\\/")[[1]])
#Check number of days in that month
last_day_of_month <- days_in_month(vecs[2])
#If the input date is higher than actual number of days in that month
#replace it with last day of that month
if (vecs[1] > last_day_of_month)
vecs[1] <- last_day_of_month
#Paste the date components together to get new modified date
dmy(paste0(vecs, collapse = "/"))
}
get_correct_date("31/02/2018")
#[1] "2018-02-28"
get_correct_date("31/04/2018")
#[1] "2018-04-30"
get_correct_date("31/05/2018")
#[1] "2018-05-31"
With small modification you can adjust the dates if they have different format or even if some dates are smaller than the first date.

R strptime: yyyyww conversion using %V behaves strange

I was trying to create a mapping from a week key to yyyyww. For example, week-1 is 200113, week-2 is 200114, and so on.
In my system, first week starts on 2001-03-26, week starts on Monday, and weeks of the year range from 01-53.
I was doing a test with %V striptime, but found strange behavior:
day1 <- as.Date("20010326", "%Y%m%d")
format(day1, "%Y%V") # output "200113", which is correct
However, when I do it inversely:
as.Date("200113", format = "%Y%V") # output "2001-11-01"
as.Date("200113 1", format = "%Y%V %u") # output "2001-11-01"
as.Date with %Y%V failed to return me the correct date. Did I miss something?
Additional testing:
format(as.Date("2001-03-26")+7*39, "%Y%V") # returns "200152"
format(as.Date("2001-03-26")+7*40, "%Y%V") # returns "200101"
format(as.Date("2001-12-31"), "%Y%V") # returns "200101"
The last two should return "200201", it seems that R did not automatically increment the year.
Additional testing: what I'm doing now is kind of nasty but working:
date <- as.Date("2001-03-26") + 7*(week_key-1),
year <- year(date),
month <- month(date),
week <- as.numeric(format(date, "%V")),
yyyyww <- ifelse(week==1 & month==12, 100*(year+1)+week, 100*year+week)

53rd week of the year in R?

I have week-date data in the form yyyy-ww where wwis the week number in two digits. The data span 2007-01 to 2010-30. The week counting convention is ISO 8601, which as you can see here on Wikipedia's "Week number" article, occasionally reaches 53 weeks in a year. For example 2009 had 53 weeks by this system, see the week numbers in this ISO 8601 calendar. (See other years; as per the Wikipedia article, 53rd weeks are fairly rare.)
Basically I want to read the week date in, convert it to a Date object and save this to a separate column in a data.frame. As a test, I reconverted the Date objects to yyyy-ww formats by format([Date-object], format = "%Y-%W", and this threw up an error at 2009-53. That week fails to be interpreted as a date by R. This is very odd, as other years which do not have a 53rd week (in ISO 8601 standard) are converted fine, such as 2007-53, whereas other years that also do not have a 53rd week (in ISO 8601 standard) also fail, such as 2008-53
The following minimal example demonstrates the issue.
Minimal example:
dates <- c("2009-50", "2009-51", "2009-52", "2009-53", "2010-01", "2010-02")
as.Date(x = paste(dates, 1), format = "%Y-%W %w")
# [1] "2009-12-14" "2009-12-21" "2009-12-28" NA "2010-01-04"
# [6] "2010-01-11"
other.dates <- c("2007-53", "2008-53", "2009-53", "2010-53")
as.Date(x = paste(other.dates, 1), format = "%Y-%W %w")
# [1] "2007-12-31" NA NA NA
The question is, how do I get R to accept week numbers in ISO 8601 format?
Note: This question summarises a problem I have been struggling with for a few hours. I have searched and found various helpful posts such as this, but none solved the problem.
The package ISOweek manages ISO 8601 style week numberings, converting to and from Date objects in R. See ISOweek for more. Continuing the example dates above, we first need to modify the formatting a bit. They must be in form yyyy-Www-w rather than yyyy-ww, i.e. 2009-W53-1. The final digit identifies which day of the week to use in identifying the week, in this case it is the Monday. The week number must be two-digit.
library(ISOweek)
dates <- c("2009-50", "2009-51", "2009-52", "2009-53", "2010-01", "2010-02")
other.dates <- c("2007-53", "2008-53", "2009-53", "2010-53")
dates <- sub("(\\d{4}-)(\\d{2})", "\\1W\\2-1", dates)
other.dates <- sub("(\\d{4}-)(\\d{2})", "\\1W\\2-1", other.dates)
## Check:
dates
# [1] "2009-W50-1" "2009-W51-1" "2009-W52-1" "2009-W53-1" "2010-W01-1"
# [6] "2010-W02-1"
(iso.date <- ISOweek2date(dates)) # deal correctly
# [1] "2009-12-07" "2009-12-14" "2009-12-21" "2009-12-28" "2010-01-04"
# [6] "2010-01-11"
(iso.other.date <- ISOweek2date(other.dates)) # also deals with this
# [1] "2007-12-31" "2008-12-29" "2009-12-28" "2011-01-03"
## Check that back-conversion works:
all(date2ISOweek(iso.date) == dates)
# [1] TRUE
## This does not work for the others, since the 53rd week of
## e.g. 2008 is back-converted to the first week of 2009, in
## line with the ISO 6801 standard.
date2ISOweek(iso.other.date) == other.dates
# [1] FALSE FALSE TRUE FALSE

Resources