DatePicker setting month wrong - java

Can anyone tell me why the date is being set to next month instead of this month?
Even though im setting the dateFormatted variable as "28/08/2014" its setting the date to "28/07/2014".
I can simply go -1 at the month but it will mess up the date in January.
Is there some other way i should be setting the date?
Thanks
UtilDateModel model;
JDatePanelImpl datePanel;
DatePickerImpl datePicker;
model = new UtilDateModel();
model.setDate(yearInt, monthInt, dayInt);
model.setSelected(true);
datePanel = new JDatePanelImpl(model);
datePicker = new JDatePickerImpl(datePanel);
// String dateFormatted = (String) result[1];
String dateFormatted = "28/08/2014";
System.out.println("Date Formatted : " + (String) result[1]);
int day = Integer.parseInt(dateFormatted.substring(0, 2)); // Correct
int month = Integer.parseInt(dateFormatted.substring(3, 5)); // Correct
int year = Integer.parseInt(dateFormatted.substring(6, 10)); // Correct
System.out.println(day);
System.out.println(month);
System.out.println(year);
model.setDate(year, month, day);
model.setSelected(true);

You're doing date parsing wrong, please use a SimpleDateFormat or the like
The problem that you are seeing is probably related to the fact that some fields are 0-based and some are 1-based.
UPDATE
Dates should not be stored as strings in the database, instead use the available date types.
Date parsing in general is much trickier than you might think. DST, leap years, language,... all comes into play.
The newest java iteration has a complete rewrite for date handling based on joda time (http://www.joda.org/joda-time/) but you can also use the "old" way of date parsing in java which is not bad, simply different.
You should look at the javadoc of SimpleDateFormat, it will tell you why you need lower case "yyyy" for example and upper case "MM". The formatter will give you a Date which you can probe with Calendar for the required fields.
All the while it will take into account all the niggling details about date handling.

I'm not known with the 'JDatePicker' package, but after doing some research, i've found this, please read article 3 on this page. It says month number is 0 based, so januari should be 0 ( 1st month minus 1).

Related

Subtracting one day off Calendar doesn't work

I am trying to build a simple program with java.util.Calendar. When trying to get the weekday before, my output always stays the same. Code and what I tried below:
Calendar c = Calendar.getInstance();
c.set(Calendar.MONTH, month);
c.set(Calendar.DAY_OF_MONTH, day);
c.set(Calendar.YEAR, year);
int date = c.get(Calendar.DAY_OF_WEEK);
return new SimpleDateFormat("EEEE").format(date).toUpperCase();
This was my code at the start. I have tried subtracting day by one:
day = day-1;
I have tried adding minus one to both the Day of Month and Day of week field:
c.add(Calendar.DAY_OF_WEEK, -1);
c.add(Calendar.DAY_OF_MONTH, -1);
I think that it has something to do with my SimpleDateFormat, but I am not sure.
I am trying to build a simple program with java.util.Calendar.
That is impossible. Specifically, the 'simple program' part. Nothing that uses Calendar is simple.
The calendar API is horrible; it makes no sense (the first month of the year is... 0, to change values, you have to use int constants, which isn't idiomatic java), and is confused about what it is trying to represent (it's not a calendar, it's a date/time value, or, is it? Is it solarflares time, appointment time, or alarmclock time? It's confused and doesn't know). That's why there is a new API: java.time. Java does not remove stuff even if it is obsolete, because that would break old code. So, the fact that Calendar is still around doesn't mean much.
Use java.time.
I think that it has something to do with my SimpleDateFormat, but I am not sure.
It doesn't. But let's forget about this silly API and use java time instead!
// note that in calendar, january is 0, and that is insane.
// in localdate, it is 1, which is sane.
// thus, assuming you have `month = month - 1;` someplace in your code...
// remove that.
LocalDate date = LocalDate.of(year, month, day);
DayOfWeek day = date.getDayOfWeek();
System.out.println(day);
Wanna go back a day? Okay.
DayOfWeek day = date.minusDays(1).getDayOfWeek();
System.out.println(day);
The reason this fails is that you aren't invoking the method you think you are. There is no SimpleDateFormat#format(int). But SimpleDateFormat extends Format, which declares Format#format(Object). Your int is boxed to Integer and then the relevant code in Format#format(Object) is
if (obj instanceof Date)
return format( (Date)obj, toAppendTo, fieldPosition );
else if (obj instanceof Number)
return format( new Date(((Number)obj).longValue()),
toAppendTo, fieldPosition );
else
throw new IllegalArgumentException("Cannot format given Object as a Date");
At this point, since the value you passed is boxed to Integer which extends Number, the second branch of the if-else is taken and your day-of-week value is converted to a date via the constructor. The number is interpreted as a millisecond value and when you subtracted 1 you changed the time by 1 millisecond, not 1 day.
All that said, you should NOT be using Calendar, use the new date/time API in the java.time package.

Calendar behavior is not compatible with LocalDate?

Hi buddies I'm in a trouble trying to migrate a behavior from calendar to localdate.
payDate.set(Calendar.DAY_OF_MONTH,payDay)
Lets imagine that payDate had the current date, 2020-01-29
for business reasons payDay can had the value of 0, so, when the previous code line is executed with the previous scenario, the result is that payDate update the date to 2019-12-31,
that is to say the the date back to the last day of the past month.
I'm not sure, the technical reason of this, if someone can explain to me this I'll be so thankful, I tried checking the java doc but it was not helpful.
So I need to replicate that behavior with LocalDate java library. From my point of view; the similar of set method from Calendar with the value of DAY_OF_MONTH in LocalDate is:
payDate.withDayOfMonth(payDay)
But when the below scenario is presented and payDay is equal to 0 I get an error:
java.time.DateTimeException: Invalid value for DayOfMonth (valid values 1 - 28/31): 0
Also I had some ideas about how can I get the same result of calendar in localDate when the rule comes on (if payDay is 0, return to the last day of previous month), but are too verbose.
If you know a similar behavior on LocalDate please help me. Thanks.
TL;DR: Use payDate = payDate.plusDays(payDay - payDate.getDayOfMonth());
The behavior of Calendar you're describing is documented in the javadoc:
Leniency
Calendar has two modes for interpreting the calendar fields, lenient and non-lenient. When a Calendar is in lenient mode, it accepts a wider range of calendar field values than it produces. When a Calendar recomputes calendar field values for return by get(), all of the calendar fields are normalized. For example, a lenient GregorianCalendar interprets MONTH == JANUARY, DAY_OF_MONTH == 32 as February 1.
When a Calendar is in non-lenient mode, it throws an exception if there is any inconsistency in its calendar fields. For example, a GregorianCalendar always produces DAY_OF_MONTH values between 1 and the length of the month. A non-lenient GregorianCalendar throws an exception upon calculating its time or calendar field values if any out-of-range field value has been set.
To show the effect of this, try setting the date of a Calendar to January 70, 2020:
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(2020, Calendar.JANUARY, 70);
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime()));
Output
2020-03-10
You would get the same result if you did:
cal.set(2020, Calendar.JANUARY, 1);
cal.add(Calendar.DAY_OF_MONTH, 69);
LocalDate is always non-lenient, so you can't set the day-of-month value to a value that is out-of-range. You can however get the same result as what Calendar does, by changing the operation to "add" instead of "set".
So, if you have a particular date, e.g. the 2020-01-29 date mentioned in the question, and you want to "set" the day-of-month value to 70 or 0, with same lenient overflow logic as Calendar has, do this:
LocalDate date = LocalDate.parse("2020-01-29");
date = date.plusDays(70 - date.getDayOfMonth());
System.out.println(date);
LocalDate date = LocalDate.parse("2020-01-29");
date = date.plusDays(0 - date.getDayOfMonth());
System.out.println(date);
Output
2020-03-10
2019-12-31
As you can see, date.plusDays(dayToSet - date.getDayOfMonth()) will give you the desired result.
Here’s how I would go about it:
LocalDate payDate = LocalDate.now(); // or whatever
int payDay = 0;
if (payDay == 0) {
// simulate `GregorianCalendar` behaviour: day 0 is the day before day 1
payDate = payDate.withDayOfMonth(1).minusDays(1);
} else {
payDate = payDate.withDayOfMonth(payDay);
}
System.out.println(payDate);
When I ran the snippet just now, the output was the date you already mentioned:
2019-12-31
If we wanted it shorter, we could use payDate.withDayOfMonth(1).minusDays(1).plusDays(payDay) or the trick from Andreas’ answer, and we would not need the if statement. I would not, though. (1) It’s harder to read. (2) It doesn’t give the validation of payDay that comes for free in the snippet above.
The confusing behaviour of Calendar comes from not range checking the argument to set(). So day 0 of the month is the day before day 1 of the month. Day -1 would be the day before that, and so forth. It’s in this snippet from the documentation (or was supposed to be, at least):
When a Calendar is in lenient mode, it accepts a wider range of
calendar field values than it produces. When a Calendar recomputes
calendar field values for return by get(), all of the calendar
fields are normalized. For example, a lenient GregorianCalendar
interprets MONTH == JANUARY, DAY_OF_MONTH == 32 as February 1.
You may read it with this snippet from the documentation of the setLenient method:
The default is lenient.
Links
Documentation of Calendar
Documentation of Calendar.setLenient()
You're not going to be able to just invoke one method to achieve the same results. If you're sure that setting DAY_OF_MONTH to 0 should cause it to roll back one month (this is the type of thing I'd run past a business analyst or product owner for a sanity check) then you're going to have to do something like this:
int payDay = 0;
LocalDate payDate = LocalDate.of(2020, Month.JANUARY, 29);
if(payDay == 0) {
payDate = payDate.minusMonths(1);
payDay = payDate.lengthOfMonth();
}
payDate = payDate.withDayOfMonth(payDay);
Another approach:
int payDay = 0;
LocalDate payDate = LocalDate.of(2020, Month.JANUARY, 29);
if(payDay == 0) {
payDate = payDate.withDayOfMonth(1).minusDays(1);
} else {
payDate = payDate.withDayOfMonth(payDay);
}

Comparing time stored in a String

I have a time in string format like "02:00" in 24 hours and I want to check it between two other time,such that "07:00"and "15:oo" .How can I check for this, as the time is in string format ?
I use the following code:
SimpleDateFormat simpDate = new SimpleDateFormat("kk:mm");
String s2=simpDate.format(date);
JLabel1.setText(s2);
now I want to check if that String s2 is inbetween "7:00" and "15:00" then set the value to another JLabel named JLabel2 as: "First Shift"
You use a SimpleDateFormat to convert the String to a Date. Then you can compare the dates together.
Read more about SimpleDateFormat here.
First, you need to parse your strings to Date object instances. You can use the DateFormat derived classes to do so (i.e. SimpleDateFormat).
Then, you can do comparisons using the millisecond-representation of both dates (obtained via getTime()) or just compare them using either after(Date date) or before(Date date).
If you need more complex operations you should use the Calendar class.
Besides, if your project works a lot with dates I'd suggest using Joda Time
EDIT (in response to comment):
Using Calendar class it would be this way. First you need a calendar instance for your 7:00 date:
Calendar cal1 = Calendar.getInstance();
cal1.set(Calendar.DATE, 12); // The day of month you are working with
cal1.set(Calendar.MONTH, 7); // The month of the year
cal1.set(Calendar.YEAR, 2012); // The year
cal1.set(Calendar.HOUR_OF_DAY, 7); // Hour in 24-hours fashion
cal1.set(Calendar.MINUTE, 0); // self-explanatory
cal1.set(Calendar.SECOND, 0);
Date shiftStart = cal1.getTime();
Then do the same for the end of the shift:
Calendar cal2 = Calendar.getInstance();
cal2.set( ... ); // Repeat almost every field from previous snippet
cal2.set(Calendar.HOUR_OF_DAY, 15); // Hour in 24-hours fashion
Date shiftEnd = cal2.getTime();
Then, you just need to check the date you want to compare is between those:
Date myDate = ... // the date you want to compare
boolean checkShift = myDate.after(shiftStart) && myDate.before(shiftEnd);
Anyway, as I already said, if you will work with dates a lot in you project I would use Joda Time, as it will ease a lot date handling.

Java Date time issue [duplicate]

This question already has answers here:
Comparing two java.util.Dates to see if they are in the same day
(14 answers)
Closed 6 years ago.
I have a problem with Date instance. I did the following:
Date startDate = new Date(); //this is from database value
Date todayDate = new Date(); //this is created locally
Now when am trying to compare them, the only issue is that the Date instance will have time, so when I check if they are equal it probably wouldn't give the same thing I expect, but rather less or more. I tested the following:
System.out.println(rsv.startDate);
System.out.println("Today date:"+todayDate);
if(rsv.startDate.equals(todayDate)){
System.out.println("Equal!");
}else if(rsv.startDate.after(todayDate)){
System.out.println("After!!");
}else{
System.out.println("Before!!!!");
}
and although both are 5th feb but it shows output of Before instead of equal. How can I remedy this? I know about SimpleDateFormat but that would change the date to strings.
Thanks,
For Date operation you can use Joda utility. Following snippet code shows compare two date :
DateTime one = new DateTime(original-Date-1);
DateTime two = new DateTime(original-Date-2);
LocalDate oneDate = one.toLocalDate();
LocalDate twoDate = two.toLocalDate();
return oneDate.compareTo(twoDate);
You can see: http://joda-time.sourceforge.net/index.html
You can strip out the time from the current Date object:
Date date = new Date();
Calendar dCal = Calendar.getInstance();
dCal.setTime(date);
dCal.set(Calendar.HOUR_OF_DAY, 0);
dCal.set(Calendar.MINUTE, 0);
dCal.set(Calendar.SECOND, 0);
dCal.set(Calendar.MILLISECOND, 0);
date = dCal.getTime();
And then make your comparision.
Alternatively, if you need in your project more date/time processing power, you can use joda date time library: http://joda-time.sourceforge.net
MidnightDate class is suitable for this specific usecase: http://joda-time.sourceforge.net/api-release/org/joda/time/DateMidnight.html
Date contains both the date and time. Equals() will only return true if the time is also the same. To make the comparison work, you need to make sure that the time portion of both Date objects is the same (eg all set to zero).

Help with java calendar logic

I am working with the Java Calendar class to do the following:
Set a start date
Set an end date
Any date within that range is a "valid" date
I have this somewhat working, and somewhat not. Please see the code below:
nowCalendar.set(Calendar.DATE, nowCalendar.get(Calendar.DATE) + offset);
int nowDay = nowCalendar.get(Calendar.DATE);
Calendar futureCalendar = Calendar.getInstance();
futureCalendar.set(Calendar.DATE, nowDay + days);
Date now = nowCalendar.getTime();
Date endTime = futureCalendar.getTime();
long now_ms = now.getTime();
long endTime_ms = endTime.getTime();
for (; now_ms < endTime_ms; now_ms += MILLIS_IN_DAY) {
valid_days.addElement(new Date(now_ms));
System.out.println("VALID DAY: " + new Date(now_ms));
}
Basically, I set a "NOW" calendar and a "FUTURE" calendar, and then I compare the two calendars to find the valid days. On my calendar, valid days will be shaded white and invalid days will be shaded gray. You will notice two variables:
offset = three days after the current selected date
days = the number of valid days from the current selected date
This works...EXCEPT when the current selected date is the last day of the month, or two days prior (three all together). I think that its the offset that is definitely screwing it up, but the logic works everywhere else. Any ideas?
Don't fiddle with milliseconds. Clone the nowCalendar, add 1 day to it using Calendar#add() in a loop as long as it does not exceed futureCalendar and get the Date out of it using Calendar#getTime().
Calendar clone = nowCalendar.clone();
while (!clone.after(futureCalendar)) {
validDays.add(clone.getTime());
clone.add(Calendar.DATE, 1);
}
(note that I improved validDays to be a List instead of the legacy Vector)
Use add instead of set in the first line, otherwise the month is not adjusted if you are at the month boundary:
nowCalendar.add(Calendar.DATE, offset);
public boolean isInRange(Date d)
{
Calendar cal = Calendar.getInstance();
cal.setTime(d);
return cal.after(startCal) && cal.before(endCal);
}
Here the startCal is the calendar instance of start time and endCal is end time.
I found the problem:
As soon as I set futureCalendar to be a clone of nowCalendar (plus the additional days), then it started working. Thanks for everyone's suggestions!

Categories

Resources