dcl-s today date inz(*Sys) is the current sytem date
How do i get the first day of the first month of the current year in this format 2017/01/01
You may want to look into the %SUBST built-in function.
date = d'1999-02-17';
time = t'01.23.45';
timestamp = z'1999-02-17-01.23.45.98765';
num = %subdt(date:*YEARS);
// num = 1999
num = %subdt(time:*MN);
// num = 23
Here's a slick trick:
dcl-proc BuildDate;
dcl-pi *n date;
pyear int(5) const;
pmonth int(5) const;
pday int(5) const;
end-pi;
dcl-ds *n;
dateds date(*iso) inz(d'0001-01-01');
year zoned(4:0) pos(1);
month zoned(2:0) pos(6);
day zoned(2:0) pos(9);
end-ds;
year = pyear;
month = pmonth;
day = pday;
test(e) dateds;
if %error;
reset dateds;
endif;
return dateds;
end-proc;
Now all you need to do to construct a valid date given Day Month and Year is:
FirstDOY = BuildDate(%subdt(%date(): *Y): 1: 1);
Related
I am trying to develop a code to generate number of working days in each month between two selected dates:
Eg: Start Date is 20-Oct-2022 and End Date is 14-Feb-2023.
I am able to generate net working days between two dates, however not for each month between the two dates.
I am expecting the code to provide output as:
Net working days in
Oct'22 is 8,
Nov'22 is 21,
Jan'23 is 22 and
Feb'22 is 10.
var startDate = new Date('20/10/2022');
var endDate = new Date('14/02/2023');
var numOfDates = getBusinessDatesCount(startDate,endDate);
function getBusinessDatesCount(startDate, endDate) {
let count = 0;
const curDate = new Date(startDate.getTime());
while (curDate <= endDate) {
const dayOfWeek = curDate.getDay();
if(dayOfWeek !== 0 && dayOfWeek !== 6) count++;
curDate.setDate(curDate.getDate() + 1);
}
return count;
}
like in above example you can calculate number of working days between two dates.
How to get the last date of a month with chrono::NaiveDate. I try to search the manual but can't found anything useful.
use chrono::{NaiveDate, Datelike};
// from January to December m = 1 - 12
for m in 1..=12 {
let end = ..... ??
let start_date = NaiveDate::from_ymd(year, m, 1); /// each month starts with 1
let end_date = NaiveDate::from_ymd(year, m, end); /// here's the problem
container.push((start_date, end_date));
}
the closest would be to use Datelike::day https://docs.rs/chrono/0.4.6/chrono/trait.Datelike.html#tymethod.day0
and subtract 1 day from it, but I don't know how to do that with NaiveDate. I'm open to any suggestion. Thanks in advance.
Proposal for requested function
The function last_day_of_month already was proposed to be added to the chrono library on GitHub, but was not accepted.
The Code
The following solution works exactly like #Zeppi's solution, but uses a more rusty approach.
An Option<NativeDate> returned from NativeDate::from_ymd_opt is used to check whether the month is the 12. month to the switch to the edge-case, where the day is the last day of the month.
fn last_day_of_month(year: i32, month: u32) -> NaiveDate {
NaiveDate::from_ymd_opt(year, month + 1, 1)
.unwrap_or(NaiveDate::from_ymd(year + 1, 1, 1))
.pred()
}
Credits to #lifthrasiir on GitHub for the code
Sources
Chrono library Issue 69: Provide days_in_month()
Chrono library Issue 29: Leap year and last day of month
You can use pred()or pre_opt().
A very dirty solution that works like this
for m in 1..=12 {
let start_date = NaiveDate::from_ymd(2022, m, 1);
let mut end_date;
if m < 12 {
end_date = NaiveDate::from_ymd(2022, m + 1, 1).pred();
} else {
end_date = NaiveDate::from_ymd(2023, 1, 1).pred();
}
println!("{:?}", end_date);
}
How can I get the last Friday of each month for the next N months in Rust? I am able to get every Friday for the next N weeks but not able to find out how to determine if it is the last Friday of a month.
Currently I have:
use chrono::{Date, Datelike, DateTime, Duration, NaiveDate, NaiveDateTime, Utc, Weekday};
...
while index < 52 {
// Works to get friday at midnight
let new_date = NaiveDate::from_isoywd_opt(
now.iso_week().year(),
now.iso_week().week(),
Weekday::Fri
).unwrap();
let naive_datetime: NaiveDateTime = new_date.and_hms(0, 0, 0);
log::debug!("{:#?}", naive_datetime);
now = now + Duration::weeks(1);
index += 1;
}
But strangely I cannot find an easy way to determine the month cadence for this. I must be missing something obvious.
I was able to get it to work with the hint from #Jmb
with this code block.
while index < 52 {
let year = now.iso_week().year();
let month = now.month();
let week = now.iso_week().week();
// Works to get friday at midnight
let new_date = NaiveDate::from_isoywd_opt(
year,
week,
Weekday::Fri,
).unwrap();
let naive_datetime: NaiveDateTime = new_date.and_hms(0, 0, 0);
if naive_datetime.day() < 7 {
let previous_friday = naive_datetime - Duration::weeks(1);
let datetime: DateTime<Utc> = Utc.from_utc_datetime(&previous_friday);
dates.push(datetime);
}
now = now + Duration::weeks(1);
index += 1;
}
log::debug!("{:#?}", dates);
I want get the current date from the system(for eg- 2021-06-22) and compare with the input date (for eg- 2021-06-22) in groovy code.I tried the below code but im getting error in month field.
TimeZone tz = TimeZone.getTimeZone('UTC');
cal.setTimeZone(tz);
int hour = cal.get(Calendar.HOUR_OF_DAY) //Get the hour from timestamp
int min = cal.get(Calendar.MINUTE) //Get the Minutes from timestamp
int sec = cal.get(Calendar.SECOND)
int day = cal.get(Calendar.DAY_OF_WEEK)
int date = cal.get(Calendar.DATE)
int month= cal.get(Calendar.MONTH)
int year= cal.get(Calendar.YEAR)
println month
What would be the Groovy way to accomplish Joda Time example below:
LocalDate startDate = new LocalDate(2016, 11, 8);
LocalDate endDate = new LocalDate(2017, 5, 1);
LocalDate thisMonday = startDate.withDayOfWeek(DateTimeConstants.MONDAY);
if (startDate.isAfter(thisMonday)) {
startDate = thisMonday.plusWeeks(1); // start on next monday
} else {
startDate = thisMonday; // start on this monday
}
while (startDate.isBefore(endDate)) {
System.out.println(startDate);
startDate = startDate.plusWeeks(1);
}
And what about by more than 1 day of the week: MONDAY and TUESDAY, for example
Given your start and end date parameters, the following Groovy code (using Groovy Date.parse() and Date.format() mix-in functions, Groovy Date + int addition, Groovy String to int coercion, and a bit of algebra) seems to do the trick:
Date startDate = Date.parse("yyyy-MM-dd","2016-11-08")
Date endDate = Date.parse("yyyy-MM-dd","2017-05-01")
Date mondayStart = startDate + 6 - ((5 + (startDate.format("u") as int)) % 7)
while (mondayStart < endDate) {
println mondayStart
mondayStart += 7
}
Having said that, the while loop at the bottom is sort of... "open-ended". You can get a more analytical equivalent using Groovy's Range literal syntax and List.step() mix-in function. The following replaces only the while loop above:
(mondayStart..<endDate).step(7) { stepDate ->
println stepDate
}
Part 2: More than Monday
In order to work with other days of the week we need to replace the constant 5 in the mondayStart assignment with a suitable sub-expression based on the day of the week. Fortunately the following expression works quite nicely:
7 - Calendar."${weekDay.toUpperCase()}"
Putting the whole thing together and massaging a bit, it looks something like this:
def weekDaysInDateRange(Date startDate, Date endDate, String weekDay = "monday") {
startDate = startDate.clearTime()
endDate = endDate.clearTime()
def offset = 7 - Calendar."${weekDay.toUpperCase()}"
def startDOW = startDate.format("u") as int
def weekDayStartDate = startDate + 6 - (offset + startDOW) % 7
(weekDayStartDate..<endDate).step(7) { stepDate ->
println (stepDate.format("yyyy-MM-dd"))
}
}
With that function defined, the following test code:
def now = new Date()
def nextMonthIsh = new Date() + 30
println "$now --> $nextMonthIsh"
println "============================================================="
["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"]
.each { weekDay ->
println """
$weekDay
=========="""
weekDaysInDateRange(now, nextMonthIsh, weekDay)
}
Gives the following result:
Mon Sep 19 09:29:24 CDT 2016 --> Wed Oct 19 09:29:24 CDT 2016
=============================================================
sunday
==========
2016-09-25
2016-10-02
2016-10-09
2016-10-16
monday
==========
2016-09-19
2016-09-26
2016-10-03
2016-10-10
2016-10-17
tuesday
==========
2016-09-20
2016-09-27
2016-10-04
2016-10-11
2016-10-18
wednesday
==========
2016-09-21
2016-09-28
2016-10-05
2016-10-12
thursday
==========
2016-09-22
2016-09-29
2016-10-06
2016-10-13
friday
==========
2016-09-23
2016-09-30
2016-10-07
2016-10-14
saturday
==========
2016-09-24
2016-10-01
2016-10-08
2016-10-15