How do I get the output of the function in Groovy - groovy

static def StartMonth() {
def date = new Date().format('MM')
def month = date.toInteger()
if (month > 6) {
month = month - 6
} else if (month <= 6) {
month = (month + 12) - 6
}
}
static void main(String[] args) {
StartMonth();
}
}
I have this and the output will be 4 (right now in October) and I want to retrieve that value so that I can have a new variable newDate = *startDate output* + '25/2019' but I do not know how to get the value back. (I am very new to this, I usually program in Javascript and even then I am still a beginner)
Thank you

In groovy you can return a value using the return value (as you can do in javascript). If there is no return a method returns the last value assigned (month in your case).
So you can either add return month in your StartMonth method. Or you can keep it as it is and just print it:
static void main(String[] args) {
println StartMonth()
}

Related

Spring schedule - last day of month not working

I wanted to run a spring scheduler job at 'last day of every month at 10:15' and 'First Sunday of every month' -
I have tried below - but it is giving error while initializing spring context:
org.springframework.boot.SpringApplication:Application startup failed
java.lang.IllegalStateException: Encountered invalid #Scheduled method 'monthEndSchedule': For input string: "L"
#Override
#Scheduled(cron = "0 15 10 L * ?")
public void monthEndSchedule() {
//
}
Though below works which runs at 'every day 1 am'
#Override
#Scheduled(cron = "0 0 1 * * ?")
public void surveyDailySchedule() {
//
}
Cron expression reference I have used : http://www.quartz-scheduler.org/documentation/quartz-2.x/tutorials/crontrigger.html
Spring Scheduler does not support the "L" input string. So, you need to do a workaround.
First, call scheduler for each of the possible last days of months (28,29,30,31).
Then, inside the function block check with an if block whether this is the last date. If it is, then perform the expected task.
Code will be like this -
#Scheduled(cron = "0 15 10 28-31 * ?")
public void monthEndSchedule() {
final Calendar c = Calendar.getInstance();
if (c.get(Calendar.DATE) == c.getActualMaximum(Calendar.DATE)) {
// do your stuff
}
}
If someone prefers to do the check with JDK8+, here it is:
#Scheduled(cron = "0 15 10 28-31 * ?")
public void doStuff() {
LocalDate date = LocalDate.now();
LocalDate last = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
if (date.getDayOfMonth() == last.getDayOfMonth()) {
//TODO: your job
}
}
This will run at 6 pm on the last 4 days of every month.

Selecting a date between certain range based on conditions using groovy

I am having a little issue with a date generator code below. The list of the code below is to ensure that a random date is selected within the summer months (May, June, July August) for availability.
So what I did is that I say if the current month is less than 5 (less than May), then select a random date between 1st May this year till 31st August this year, else if the current month is past 7 (past July), then select a random date between 1st May next year till 31st August next year.
Now I notice a little glitch in my code I require help with. As I ran the code below today (8th May), it is possible that the date the random generator selects could be in May before today's date. Actually the issue is I don't have anything to handle when I am in the current months. So I think I require a little refactoring.
What i would like is that it checks the current date and if it between May to July (so not less than May or more than July), then check today's date and pick a date between today till the 31st August this year.
My brain has been fried and for some strange reason I am struggling on something which logically makes sense, but I've just been having issues programming it.
import groovy.time.TimeCategory
//def dataSet = testRunner.testCase.getTestStepByName("Properties")
// Select the current test data line
def dateFormat = 'yyyy-MM-dd'
def getNumberInRange = { min, max -> new Random().nextInt(max + 1 - min) + min }
def isTodayBeforeMay = { Calendar.MONTH < 5 }
def isTodayAfterJuly = { Calendar.MONTH > 7 }
//Get the number of days between today and given date
def getDifferenceDays = { targetDate, closure ->
def strDate = closure (targetDate)
def futureDate = new Date().parse(dateFormat, strDate)
TimeCategory.minus(futureDate, new Date()).days
}
//Get the offset between today and max date i.e.,31 august
def getOffSetDays = { date ->
//Need to change the date range if needed.
//As per OP, May to August is mentioned below
def max = getDifferenceDays(date) { "${it[Calendar.YEAR]}-08-31" }
def min = getDifferenceDays(date) { "${it[Calendar.YEAR]}-05-01" }
getNumberInRange(min, max)
}
def now = new Date()
def nextYearNow = now.updated(year: now[Calendar.YEAR] + 1)
def selected
def finalDate
log.info "Today : $now"
log.info "Next year same date : $nextYearNow"
if (isTodayBeforeMay()) {
selected = now
} else if (isTodayAfterJuly()) {
selected = nextYearNow
} else {
throw new Error("Not implemented for the days between 1st May to 30th July")
}
def offset = getOffSetDays(selected)
//Add the offset days to now
use(TimeCategory) {
finalDate = now + offset.days
}
All you need is to implement the else condition instead of throw new Error(..) below (code excerpt from the question):
If you read the code, it is crystal clear each condition and error message as place holder for the unknown data range in below and which is now you wanted it to be handled.
if (isTodayBeforeMay()) {
selected = now
} else if (isTodayAfterJuly()) {
selected = nextYearNow
} else {
throw new Error("Not implemented for the days between 1st May to 30th July")
}
Just add the below statement in the last else in place of threw new Error
selected = getOffSetDays(now)
EDIT:
You can try quickly online Demo
EDIT 2: Looks the above is not working at times randomly, so updating the answer:
import groovy.time.TimeCategory
def dateFormat = 'yyyy-MM-dd'
def getNumberInRange = { max, min = 1 -> new Random().nextInt(max + 1 - min) + min }
def isTodayBeforeMay = { Calendar.MONTH < 5 }
def isTodayAfterJune = { Calendar.MONTH > 6 }
//Get the number of days between today and given date
def getDifferenceDays = { targetDate, closure ->
def strDate = closure (targetDate)
def futureDate = new Date().parse(dateFormat, strDate)
TimeCategory.minus(futureDate, new Date()).days
}
def getPaddedString = { num, len = 2, padwith = '0' ->
num.toString().padLeft(len, padwith)
}
//Get the offset between today and max date i.e.,31 august
def getOffSetDays = { date, minMonth = 5, minDay = 1 ->
//Need to change the date range if needed.
//As per OP, May to August is mentioned below
def max = getDifferenceDays(date) { "${it[Calendar.YEAR]}-08-31" }
def min = getDifferenceDays(date) { "${it[Calendar.YEAR]}-${getPaddedString(minMonth)}-${getPaddedString(minDay)}" }
getNumberInRange(max, min)
}
def now = new Date()
def nextYearNow = now.updated(year: now[Calendar.YEAR] + 1)
def selected
def finalDate
println "Today : $now"
println "Next year same date : $nextYearNow"
if (isTodayBeforeMay()) {
selected = now
} else if (isTodayAfterJune()) {
selected = nextYearNow
}
def dayz = getNumberInRange(getDifferenceDays(now) { "${it[Calendar.YEAR]}-08-31" })
def offset = selected ? getOffSetDays(selected) : dayz
offset = offset > 0 ? offset : now[Calendar.DAY_OF_MONTH]+1
//Add the offset days to now
use(TimeCategory) {
finalDate = now + offset.days
}
println "Final future date is : $finalDate"
println "Final future date is(formatted) : ${finalDate.format(dateFormat)}"
assert now <= finalDate
This Demo generate the date 1000 times just to make sure the date is ok.

Array of dates returns object System datetime not the actual value of the array

Question is I have a function call "GetDatesBetween" what this does is looks at my two datepickers leave_s_dp and leave_e_dp and gets the dates between them. I then want to turn this array into a string for use in my full_range text box, But it always returns System.DateTime[]. Any help would be greatly appreciated.
public:
List<DateTime> ^GetDatesBetween(DateTime startDate, DateTime endDate)
{
List<DateTime> ^allDates = gcnew List<DateTime>();
for (DateTime date = startDate; date <= endDate; date = date.AddDays(1))
{
allDates->Add(date.Date);
}
return allDates;
}
private:
System::Void submit_button_Click(System::Object^ sender, System::EventArgs^ e) {
array<DateTime> ^dates = GetDatesBetween(leave_s_dp->Value.Date, leave_e_dp->Value.Date)->ToArray();
//array<DateTime> ^dates = GetDatesBetween(leave_s_dp->Value, leave_e_dp->Value)->ToArray();
String ^ days_between = dates->ToString();
full_range_text->Text = days_between;
}
You're calling ToString() on an array. That doesn't do what you expect it to. It's not clear exactly what you do expect it to do, but it's almost certainly not what you want.
You quite possibly want to call string.Join, e.g.
dates_between = String::Join(", ", dates);
That will just use the default date format though - which may not be what you want either.

From Date and To Date From Previous Weeks

I am working in C#.Net. I need the From Date and To Date.
For Ex : If i selected "Last Week" means, i should get 15th April - 21st April.
" 2 Weeks Ago " means, 8th April - 14th April. Same as for 3 Weeks ago, 4 Weeks ago etc..
How to get the From Date and To Date..
i made a console program..itz working fine.. chek it out
static void Main(string[] args)
{
Console.WriteLine("Enter week number");
int week = int.Parse(Console.ReadLine());
var weekStartDay = DayOfWeek.Monday;
int daysInAWeek = 7;
DateTime thisWeekStarttingDate = DateTime.Now.Subtract(new TimeSpan((int)DateTime.Now.DayOfWeek - (int)weekStartDay, 0, 0, 0)).Date;
DateTime fromDate = thisWeekStarttingDate.Subtract(new TimeSpan(daysInAWeek * week, 0, 0, 0));
DateTime toDate = fromDate.AddDays(daysInAWeek-1);
Console.WriteLine("from date:" + fromDate.ToShortDateString());
Console.WriteLine("to date:" + toDate.ToShortDateString());
Console.ReadKey();
}
var currentWeek_StartDate = GetStartWeekDate_By_Date(DateTime.Now.Date);
var lastWeek_StartDate = GetStartWeekDate_By_WeekIndex(currentWeek_StartDate, -1);
var lastWeek_EndDate = GetEndWeekDate_By_StartWeekDate(lastWeek_StartDate);
public static DateTime GetStartWeekDate_By_Date(DateTime date)
{
return date.AddDays(-(int)date.DayOfWeek);
}
public static DateTime GetEndWeekDate_By_StartWeekDate(DateTime date)
{
return date.AddDays(6);
}
public static DateTime GetStartWeekDate_By_WeekIndex(DateTime date, int weekIndex)
{
return date.AddDays(weekIndex * 7);
}

Linq-Entities: Fetch data excluding the overlapping data ranges, pick the largest period

I have 2 tables, Imports and Periods.
Imports has the following structure:
AdminID, PeriodID, Some more fields
1, 1
1, 2
1, 6
1, 50
Periods table has the following structure:
PeriodID, PeriodType, StartDate, EndDate, Description
1, 1, 2007-01-01, 2007-12-31, Year 2007
2, 2, 2007-01-01, 2007-03-31, Quarter 1 2007
3, 2, 2007-04-01, 2007-06-30, Quarter 2 2007
4, 2, 2007-07-01, 2007-09-30, Quarter 3 2007
5, 2, 2007-10-01, 2007-12-31, Quarter 4 2007
6, 3, 2007-01-01, 2007-01-31, January 2007
.
.
.
50, 2, 2011-01-01, 2011-03-31, Quarter 1 2011
Now, I need to build a linq query to fetch only the largest period(ignoring the smaller overlapping periods) based on the data in Imports table!
When I query for AdminID = 1, I should only get PeriodID = 1 & 50, ignoring/excluding the PeriodIDs 2 & 6 as they overlap in 1 and 50 as there is no overlapping data yet!
You, can the max help for picking the largest period and while retrieving the values by comparing the PeriodIDs in both tables right.
I'm not sure whether there is a convenient way to do this in the database, but when you pull the data locally, you can do in-memory LINQ queries, if this is appropriate. You need to do this in thee steps.
Step 1: Define a Range class that allows you to do comparisons on periods (see below).
Step 2: Pulling the periods from the database:
var ranges = (
from period in context.Periods
where period.Imports.Any(i => i.AdminID == adminId)
select new Range(period.StartDate, period.EndDate.AddDays(1)))
.ToArray();
Note the .ToArray() to pull everything locally.
Step 3: Aggregating / merging all the periods into a list of non-overlapping periods:
var mergedPeriods = (
from range in ranges
select ranges.Where(p => p.OverlapsWith(range))
.Aggregate((r1, r2) => r1.Merge(r2)))
.Distinct();
For this to work you need a specially designed Range type that contains OverlapsWith, Merge and Equals methods. It might look like this:
public class Range : IEquatable<Range>
{
public Range(DateTime start, DateTime exclusiveEnd)
{
if (exclusiveEnd < start)
throw new ArgumentException();
this.Start = start; this.End = exclusiveEnd;
}
public DateTime Start { get; private set; }
public DateTime End { get; private set; }
public TimeSpan Duration { get { return this.End - this.Start; } }
public Range Merge(Range other)
{
if (!this.OverlapsWith(other)) throw new ArgumentException();
var start = this.Start < other.Start ? this.Start : other.Start;
var end = this.End > other.End ? this.End : other.End;
return new Range(start, end);
}
public bool Contains(Range other)
{
return this.Start <= other.Start && this.End > other.End;
}
public bool OverlapsWith(Range other)
{
return this.OverlapsOnStartWith(other) ||
other.OverlapsOnStartWith(this) ||
this.Contains(other) ||
other.Contains(this);
}
private bool OverlapsOnStartWith(Range other)
{
return this.Start >= other.Start && this.Start < other.End;
}
public bool Equals(Range other)
{
return this.Start == other.Start && this.End == other.End;
}
}
I hope this helps.
Well, after a long struggle, I did find an answer! With a single query to database!
And for everyone's benefit posting the same.
var oImportPeriods =
from o in Imports
where o.Administration.AdminID == 143
orderby o.Period.PeriodID
select o.Period;
var oIgnorePeriodList = (
from oPeriod in oImportPeriods
from oSearchPeriod in oImportPeriods
.Where(o => o.PeriodID != oPeriod.PeriodID)
where oPeriod.StartDate >= oSearchPeriod.StartDate
where oPeriod.EndDate <= oSearchPeriod.EndDate
select oPeriod.PeriodID)
.Distinct();
var oDeletablePeriods = oAdministrationPeriods
.Where(o => !oIgnorePeriodList.Contains(o.PeriodID));
foreach(var o in oDeletablePeriods)
Console.WriteLine(o.Name);

Resources