Struts: Highlighting Date Range in Calendar (JQuery/Javascript) - java

Thank you very much in advance for reading.
I'm programming a web application in Struts.
I'm using a JQuery datepicker 1.7 as a calendar on the sidebar on the user's view. (It's the best option I could find)
I would like to highlight in the calendar a group of days starting from initial date (startDate) until the end (endDate) of several reminders I have in an array. This way, the user will be able to see on the calendar of the application, all the available days he has left in order to take action for each of his reminders.
I already have my array of reminders which I can access from the view. I was able to implement it properly thanks to guidance from a great fellow around here.
This is my javascript function for the datepicker:
$(function(){
$('#datepicker').datepicker({
flat: true,
numberOfMonths: [1,1],
dateFormat: 'dd/mm/yy',
beforeShowDay: highlightDays
});
There is another function, namely, highlightDays which is the one that is causing me trouble:
It's parameter is the array "reminders" such that reminders[i].start is the startDate, and reminders[i].end is the endDate of reminder i, with i = number of reminders in the array.
function highlightDays(reminders) {
for (var i = 0; i < reminders.length; i++) {
/** Below:
*If startDate is smaller than endDate,
*then highlight the days inbetween.
*/
if (new Date(reminders[i].start).toString() <=
new Date(reminders[i].end).toString() ){
return [true, 'ui-state-highlight'];
}
} //Otherwise do not highlight
return [true, ''];
}
The problem is the calendar won't even show up when I open the application and log in. And the Apache Log or output do not show any errors. I'd like to know, where do you think I might be wrong? I will keep investigating, but I'd really appreciate your input!
P.D: I can access the elements of the array of reminders (endDate, startDate) and print these dates on screen, so that means the reminders array is not empty.
Thank you once again for taking the time to read.

From http://jqueryui.com/demos/datepicker/#event-beforeShowDay
The function takes a date as a parameter and must return an array with [0] equal to true/false indicating whether or not this date is selectable, [1] equal to a CSS class name(s) or '' for the default presentation, and [2] an optional popup tooltip for this date. It is called for each day in the datepicker before it is displayed.
Your callback function is not accepting a single date as a parameter, it's taking an array of date ranges.
You might want to figure out how to call the highlightdays function inside the loop of remdinder values.

Related

Reset counter after everyday Java GUI

I am trying to make a billing menu for a software. What i am trying to do is, I want to assign a bill id to each bill using the date, say 24/11/2022 will be converted as 24112022. This will be followed by a count as: 24112022-01. I want this counter to reset whenever the date changes. I can't figure it out. Any solutions?
Here is the code I am using to get the date values and use them as my bill id
LocalDate date=LocalDate.now();
int d=date.getDayOfMonth();
int m=date.getMonthValue();
int y=date.getYear();
billId=String.valueOf(d)+String.valueOf(m)+String.valueOf(y)+counter++;
"I want this counter to reset whenever the date changes."
Think analytically (re-framing the question for this context):
a) You want a counter to reset when the date changes
b) When the date changes, you want the counter reset
c) Upon a data change, reset the counter.
So, you may want to occasionally check the time and see if it has changed (having a stored value to compare against) or overwrite an existing method that changes the day so that it would also reset the value.

Check date range in java without time AND using jodatime

I have a date supplied by the user and of course today's date.
I'm attempting to verify that the difference between the 2 days is at least 2 weeks. I've done this using standard libraries - but I'm attempting to do this using jodaTime and I'm having some difficulty.
// BAD CODE - doesn't work
// NOTE: getUserSuppliedDate() returns an instance of java.sql.Date
// Also assume that validation prior to this call has been run that
// validates that the userSuppliedDate comes AFTER today's date - not sure if
// that is relevant in the context I'm attempting to use these particular jodaTime APIs.
DateTime jodaStartDate = new DateTime(getUserSuppliedDate());
if (Days.daysBetween(jodaStartDate, DateTime.now()).isLessThan(Days.days(14))) {
System.out.println("Bad user. You have chosen...poorly.");
}
else {
System.out.println("Well done user. You have supplied wisely.");
}
// GOOD CODE ---- ? Help =)
Your code gives you the wrong result because the dates supplied to Days.daysBetween() are in the wrong order. Since you specified that the user supplied date comes after the current date, your approach will result in a negative number of days.
It will work correctly if you switch the order, putting the earliest date first.
Compare the following two:
DateTime jodaStartDate = new DateTime().withYear(2018)
.withMonthOfYear(7)
.withDayOfMonth(5); // 15 days from now
System.out.println(Days.daysBetween(jodaStartDate, DateTime.now())); // "P-15D"
System.out.println(Days.daysBetween(DateTime.now(), jodaStartDate)); // "P15D"
In the first case, -15 days will evaluate to less than 14 days.
Using weeks instead of days, you'd run into the same problem:
System.out.println(Weeks.weeksBetween(jodaStartDate, DateTime.now())); // "P-2W"
System.out.println(Weeks.weeksBetween(DateTime.now(), jodaStartDate)); // "P2W"

Java: addToDay function

I'm trying to setup my addToDay function. I'm currently stuck on how to proceed with this or even write it correctly. The function itself will take a variable that ranges from -100 to 100. So you would basically add that variable to the current and if it was below the 0 then subtract a month or if it was above the months max day then add a month. Which i have that function setup so all i would have to do is call addToMonth with the correct amount. My problem lies within the amount of days each month has. For example, October has 31 days while November has 30. I have a function that will return the number of days in the current set month so i can call that to get how many max days should be in the current month. I'm thinking maybe a while loop would work but i just wanted to get anyone's thoughts on the best way to set it up.
I have 3 private ints: month, day, year. These are what need to be changed. I have both addTo functions for month and year setup already.
Here are some other functions i have created that can be used in this:
1. addToMonth(int delta) - changes the current month depending on the given parameter
2. getDaysInMonth() - will return the days in a month depending on the month itself
3. validateDay() - Will return true or false if the days fall outside the wanted requirements.
I don't want to use the calendar utility
I also don't want to use any other utilities. Just the base code with Junit for testing
Joda's plusDays() function and Java 8 LocalDate already has the logic that you are trying to achieve
Alright so i ended up just copying my original addToMonth function and modifying it abit to fit with days. So far it works but i do think it'll fail in the cases of different amounth of days not lining up.

Mutually restricting begin and end date-times using p:calendar (no validation)

We have a requirement to present two p:calendar components to the user, representing a start and end date each. Both datetimes have dates, hours and minutes.
PrimeFaces has perfect mindate, maxdate, minHour, maxHour, minMinute, and minMinute attributes available.
The requirement now is:
It is impossible to set the start datetime to anything greater than or equal to the end datetime.
It is impossible to set the end datetime to anything less than or equal to the end datetime.
The following equation should hold true:
begin datetime < end datetime
Now we tried the following JSF:
<p:calendar id="begin-date"
value="#{debugManager.selectedBeginDate}"
mindate="#{debugManager.minBeginDate}"
maxdate="#{debugManager.maxBeginDate}"
maxHour="#{debugManager.maxBeginHour}"
maxMinute="#{debugManager.maxBeginMinute}"
pattern="yyyy-MM-dd HH:mm"
showButtonPanel="true"
readonlyInput="true"
navigator="true"
showOn="button"
required="true">
<p:ajax event="dateSelect" update="end-date" />
</p:calendar>
<p:calendar id="end-date"
value="#{debugManager.selectedEndDate}"
mindate="#{debugManager.minEndDate}"
minHour="#{debugManager.minEndHour}"
minMinute="#{debugManager.minEndMinute}"
pattern="yyyy-MM-dd HH:mm"
showButtonPanel="true"
readonlyInput="true"
navigator="true"
showOn="button">
<p:ajax event="dateSelect" update="begin-date" />
</p:calendar>
Here's an examplary min/max method (mindate of end-date):
public Date getMinEndDate()
{
return this.getSelectedBeginDate();
}
As you can see, the minimum end date is the currently AJAX-selected begin date. Setting an end date correctly disallows setting the begin date past the end date.
The problems start when involving the time into the equation...
Since the interface of p:calendar has separate methods, the bean has to provide the logic:
public int getMinEndHour()
{
Date selectedBeginDate = this.getSelectedBeginDate();
Date selectedEndDate = this.getSelectedEndDate();
if ( selectedBeginDate != null && DateUtil.isSameDay( selectedBeginDate, selectedEndDate ) )
{
return DateUtil.getHourOf( selectedBeginDate );
}
return ComplianceConstants.DEFAULT_COMPLIANCE_CASE_MIN_END_HOUR;
}
This basically only says if a begin date has been set and it the begin and end dates are currently the same, restrict the selectable end hour (minHour of end-date) to the begin hour.
Operations:
Set the begin datetime to 2013-04-20 12:34 (legit)
Set the end datetime to 2013-04-22 00:00 (legit)
Now the time for end date sits on 00:00 and selecting a calendar date 2013-04-20 should be allowed as long as the end time is somehow adjusted to at least 12:35.
The p:calendar component however cannot know this and now
sets the end datetime to 2013-04-20 00:00 (legit, but false)
...
The problem now is that when the user presses a certain new end date in the calendar, the mindate/maxdate attributes cannot restrict the user to hit the the same as the begin date. If the end date time now happens to be before the same begin date's time there's nothing we can do about it (which is wrong).
The followup problem now is that the user is able to close the calendar and just press the submit button to insert false data into the DB. Of course, a validator could/should be run, but we have to somehow achieve this without a validator.
What we were trying next was to patch the setSelectedBeginDate( Date selectedBeginDate ) and setSelectedEndDate( Date selectedEndDate ) methods to adjust the set java.util.Date time portions if the dates were on the same day. Something like this:
public void adjustSelectedEndDate()
{
if ( this.selectedEndDate != null )
{
this.log.infov( "adjustSelectedEndDate: b-hour = {0}, e-hour = {1}", DateUtil.getHourOf( this.selectedBeginDate ), DateUtil.getHourOf( this.selectedEndDate ) );
if ( DateUtil.isSameDay( this.selectedBeginDate, this.selectedEndDate ) &&
( DateUtil.getHourOf( this.selectedEndDate ) < DateUtil.getHourOf( this.selectedBeginDate ) ) ||
DateUtil.getHourOf( this.selectedEndDate ) == DateUtil.getHourOf( this.selectedBeginDate ) && DateUtil.getMinuteOf( this.selectedEndDate ) <= DateUtil.getMinuteOf( this.selectedBeginDate ) )
{
this.log.info( "Adjusting selected end date!" );
this.selectedEndDate = DateUtil.addOneMinuteTo( DateUtil.copyTime( this.selectedBeginDate, this.selectedEndDate ) );
}
}
}
This required us to add #this to the update attribute of each p:calendar so that the respective getters (getSelectedBeginDate() and getSelectedEndDate + the min/max limiters) will be called during update.
Placing an #this on the update however confuses the p:calendar components, making the time sliders only slidable once. Subsequent slider events are simply ignored, behaving broken.
Q's
How do you generally approach solving this?
Is using p:remoteCommand the way to achieve what we want?
Optional Q:
Why hasn't the PrimeFaces p:calendar been implemented to provide a single minDateTime and maxDateTime, which could potentially solve the problems at hand?
I bet this scenario I described has already been solved before. I'd very much appreciate if you could describe the approach you managed to solve this (or even share a partly solution).
Preface:
I don't work with JSF, but there are a couple of things that might steer you back to where you want to be:
a) when working with just the date portion of a dateTime in a standard calendar, consider using:
someCalendar.set(Calendar.MILLISECOND, 0)
b) consider using joda-time, as it seems to be frequently recommended (here, here , and many other places) over the standard library for correctness, performance, and ease of use in many situations.
c) Make sure your bean scope is surviving each ajax call (not redirecting, only sending standard post-backs, etc) and each event handler is getting the faces context (eg. FacesContext facesContext = FacesContext.getCurrentInstance();)
d) mindate and the like probably don't work like you expect , and I don't expect that automatic behavior can be quite so easily interjected.
When those options aren't available, and you have to do it all yourself with what you have:
Philisophical / UX:
The first thing I would do is remove the expectation of arrangement or perspective from the pair of dates. Don't treat the pair as a vector that exposes or expects a direction on the timeline.
In other words, is a start or from date always less than or earlier than an end or to date? No, as can be seen for a query of historical data, or for applying corrections to events that have either yet to happen or have already happened?
This connotation can easily confuse a user as to whether they are going 'back to' or 'forward from' (and can easily confuse yourself). Instead I would treat a pair of dates with a time-period between them as just and simply that a pair of dates or a range or a period that declares an interval, and infer their relative position on the timeline depending on the any consequently chosen values. In this way you can honor the respective and inherent requirements that the dates never be equal, and the left is always to the left, the right always to the right.
We can't infer what 'start' or 'from' means, but we can infer some meaning and relative relationship: a right, a left, and a between on a chronological timeline. Note: Always resolve dates to UTC before doing any calculation or comparison.
long oneDateValue = oneDate.toUtc().toMilliseconds();
long anotherDateValue = anotherDate.toUtc().toMilliseconds();
long right = max (oneDateValue, anotherDateValue);
long left = min (oneDateValue, anotherDateValue);
Evaluating Precision:
The second thing I would look at when working with a range of dates in any language is similar to how you might deal with floating point numbers. For comparisons, do not compare for equality, but instead compare the delta to an "acceptable error level". In other words, the application is really only concerned with a certain degree of precision, so make sure that only that precision is captured and considered:
const int dateTimeResolutionInMs = 86400000; // milliseconds per day
public bool areEssentiallySame(long left, long right) {
// the difference between right and left is less than our precision
// requires, thus dates are effectively the same
return (right - left < dateTimeResolutionInMs);
}
Coercing Precision:
Thirdly, how do we resolve the difference in values even if within the range of the resolution? (Out application was given more precision than it can handle or expect or needs).
long diff = value % dateTimeResolutionInMs;
Truncate: return value - diff;
Nearest (w/bias): return value + (diff < dateTimeResolutionInMs/ 2) ? -1 * diff : dateTimeResolutionInMs - diff;
Others: there are lots of other strategies for either shrinking or expanding a value to a preferred resolution or precision
Addendum:
As far as getting post-backs/Ajax calls to return a view with the values you expect for the events fired by a calendar element, you may want to separate that concern off to a new question if the note in the preface didn't get you anywhere, and you know for certain your bean is properly registered and recognized. You may have some browser/browser-version specific issues that contribute to the undesired behavior, and like anything else, there are issues, both known and unknown.

How can I change time format of TimePickerDialog dynamically?

I have a button, on click on the which the time format of a TimePickerDialog should change from 12 hours to 24 hours and vice versa.
I know I have to use onPrepareDialog(), but how can I change the time format inside onPrepareDialog ?
Any help is appreciated!
Thank you.
Finally did a work around to achieve this!.
Instead of using onPrepareDialog(),
I used a variable to keep tack of whether time should be shown in 24hrs or 12hrs format.
Boolean is24HoursSet;
which will be set to true when 24 hrs is selected by user, else false.
I added 2 constants
TIME_IN_12_HOURS //and
TIME_IN_24_HOURS
both for 12 hours and 24 hours format.
In touch listener, it calls showDialog().
//checks the variable, and calls according showdialog.
if(is24HoursSet)
{
showDialog(START_TIME_24);
}
else
{
showDialog(START_TIME_12);
}
which are handled in switch cases of onCreateDialog() by creating new object for
TimePickerDialog, with true or false as the last parameter of constructor which opens the timpicker with corresponding time formats. :)
Is it what you are looking for:
setIs24HourView(Boolean is24HourView);
Documentation

Categories

Resources