I have a Booking Class which has a Date variable in it.
Basically, I want to do add a new variable to ArrayList called "bookings". It works for SSN ,but Date type does not pass in this way. Why is it and what should I do to fix this situation?
Code in my "main"
bookings.add(new Booking(new Date(18,11,2020), SSN));
Here is Booking Class
public class Booking {
private Date bookingDate;
private int SSN;
public Booking(Date bookingDate, int SSN) { // constructor
this.bookingDate=bookingDate;
this.SSN=SSN;
}
}
You are not using the Date constructor properly.
The constructor for Date is in your case:
new Date(int year, int month, int date);
You should be using:
Date date = new Date(120, 11, 18);
Which returns
Fri Dec 18 00:00:00 EST 2020
ALSO: Take note that the year is actually the year - 1900 (e.g, the number of years from 1900).
It is now recommended to use use Calendar.set(year + 1900, month, date, hrs, min) or GregorianCalendar(year + 1900, month, date, hrs, min).
java.time
… and what should I do to fix this situation?
I very strongly recommend that you’re using java.time, the modern Java date and time API, for your dates. The LocalDate class from java.time represents a date without time of day. It’s got a couple of well-working factory methods, so constructing the date that we want is straightforward and trouble-free.
public class Booking {
private LocalDate bookingDate;
private int ssn;
public Booking(LocalDate bookingDate, int ssn) {
this.bookingDate = bookingDate;
this.ssn = ssn;
}
}
Now your main code could be:
bookings.add(new Booking(LocalDate.of(2020, Month.NOVEMBER, 11), ssn));
Many will find the code easier to read if we break it up a bit:
LocalDate newBookingDate = LocalDate.of(2020, Month.NOVEMBER, 11);
Booking newBooking = new Booking(newBookingDate, ssn);
bookings.add(newBooking);
You notice that there are no funny numberings. Year 2020 is 2020, and you may alternatively pass November as the number 11 if you prefer. Isn’t there still the risk of putting the arguments in the wrong order?
LocalDate newBookingDate = LocalDate.of(11, Month.NOVEMBER, 2020);
This throws:
Exception in thread "main" java.time.DateTimeException: Invalid value
for DayOfMonth (valid values 1 - 28/31): 2020
Read the message. It tells us that we put 2020 where the day of month was expected. Enjoy how much more helpful this is than the behaviour of the deprecated Date constructor that you tried to use.
Aside: a note on naming
Variables in Java begin with a lowercase letter, so prefer ssn over SSN. Also when in the domain SSN is an abbreviation and always written in upper case.
Link
Oracle tutorial: Date Time explaining how to use java.time.
Related
This question already has answers here:
Convert day of the year to a date in java
(2 answers)
Closed 3 years ago.
In the below Java class, I need to write the logic of converting an int to Date as explained below. And this program is not related to adding number of days to current date.
If endDay value is 1, then date should print as Jan 1st 2020.
If endDay value is 28, then date should print as Jan 28th 2020.
If endDay value is 35, then date should print as Feb 4th 2020.
If endDay value is 60, then date should print as Feb 29th 2020.
If endDay value is 70, then date should print as March 10th 2020.
Note: value of endDay (1) always starts from January 1st of every year.
import java.util.Date;
public class TestDate
{
public void startEndDate(int endDay)
{
Date date=new Date();
//logic to print the date here
System.out.println("For the given end day of "+endDay+" the date returned is : "+date);
}
public static void main(String[] args)
{
startEndDate(35);
startEndDate(49);
startEndDate(70);
}
}
Can any one suggest me the ideas on how to write the logic for above one ?
java.time and Year.atDay()
public static void startEndDate(int endDay)
{
LocalDate date = Year.of(2020).atDay(endDay);
System.out.println("For the given end day of " + endDay
+ " the date returned is : " + date);
}
Let’s try it out:
startEndDate(35);
startEndDate(49);
startEndDate(70);
Output is:
For the given end day of 35 the date returned is : 2020-02-04
For the given end day of 49 the date returned is : 2020-02-18
For the given end day of 70 the date returned is : 2020-03-10
The documentation of Year.atDay() explains:
Combines this year with a day-of-year to create a LocalDate.
Please fill in your desired year where I put 2020.
I recommend you don’t use Date. That class is poorly designed and long outdated. Instead I am using Year and LocalDate, both from java.time, the modern Java date and time API.
A comment suggested regarding your question as a question of adding a number of days to December 31 of the previous year. IMO regarding it as finding a date from the number of the day-of-year gives a somewhat more elegant solution.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Documentation of Year.atDay(int dayOfYear)
Documentation of LocalDate.ofYearDay(), a good alternative
I am using the below code to retrieve the last day in the previous month - Ex: May. But it is returning 30 days instead of 31.
The code given below
package net.vcmg.date;
import java.util.Calendar;
import java.util.Date;
import org.apache.commons.lang.time.DateUtils;
public class LastDayPreviousMonth {
public static void main(String[] args) {
Date lastDateOfPreviousMonth = addMonths(lastDayOfTheMonth(today()), -1);
System.out.println("lastDateOfPreviousMonth: "+lastDateOfPreviousMonth);
}
//the below method is from Utils.java
public static Date lastDayOfTheMonth(Date d) {
Calendar cal = Calendar.getInstance();
cal.setTime(d);
int actualMax = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
cal.set(Calendar.DAY_OF_MONTH, actualMax);
return cal.getTime();
}
public static Date addMonths(Date date, int numMonths)
{
return DateUtils.addMonths(date, numMonths);
}
public static Date today()
{
return truncDate(now());
}
public static Date now()
{
// will cut-off milliseconds
return new Date( (System.currentTimeMillis()/1000) * 1000);
}
public static Date truncDate (Date date) {
return DateUtils.truncate(date, Calendar.DATE);
}
}
Here, when i call the lastDateOfPreviousMonth in the main method, it is returning 30 days alone. Not the 31 , May contains 31 days actually. Please help.
Java 8
If you are not constraint to use the old Date it will be better to use the new java.time.LocalDate
LocalDate previousMonth = LocalDate.now().minusMonths(1);
LocalDate start = previousMonth.withDayOfMonth(1);
LocalDate end = previousMonth.withDayOfMonth(previousMonth.lengthOfMonth());
System.out.println(start);
System.out.println(end);
Output
2019-05-01
2019-05-31
Edit
For your implementation, change the order of methods
addMonths - get the current date and provide the previous month addMonths(new Date(), -1)
lastDayOfTheMonth - get the last day of the previous month lastDayOfTheMonth(addMonths(new Date(), -1))
Date lastDateOfPreviousMonth = lastDayOfTheMonth(addMonths(new Date(), -1));
Output
lastDateOfPreviousMonth: Fri May 31 10:46:13 EEST 2019
Try this:
public static void main(String[] args) {
Date lastDateOfPreviousMonth = lastDayOfTheMonth(addMonths(today(), -1));
System.out.println("lastDateOfPreviousMonth: " + lastDateOfPreviousMonth);
}
When you call lastDayOfTheMonth for today() day will be 30. And after minus one month result expected will be 30, not 31.
It’s a logical error in the way you have thought out your program/algorithm. You are first finding the last day of the month, in this case June 30. You are then subtracting 1 month. That gives May 30 regardless of the fact that there are 31 days in May (it’s not explicit from the documentation of DateUtils.addMonths that it works this way, but it uses the poorly designed and outdated Calendar class internally, so this is what we should expect).
Instead do things in the opposite order. First find the previous month:
YearMonth lastMonth = YearMonth.now(ZoneId.of("Asia/Kolkata")).minusMonths(1);
2019-05
Since the new month doesn’t begin at the same point in time in all time zones, I recommend that you state your desired time zone as shown.
Only then find the last day of the month:
LocalDate lastDayOfLastMonth = lastMonth.atEndOfMonth();
2019-05-31
Avoid Date and Calendar
I recommend you don’t use Date and Calendar. Those classes are poorly designed and long outdated. Instead use LocalDate and other classes from java.time, the modern Java date and time API. This will also save you from the external dependency on Apache DateUtils since its functionality is generally built into the modern classes.
Links
Documentation of org.apache.commons.lang3.time.DateUtils.addMonths
Oracle tutorial: Date Time explaining how to use java.time.
I have a method to view a calendar in Java that calculates the date by year, day of the week and week-number.
Now when I calculates the dates from 2017 everything works. But when I calculates the dates from January 2018 it takes the dates of year 2017.
My code looks like
import java.time.temporal.IsoFields;
import java.time.temporal.ChronoField;
import java.time.LocalDate;
// .....
LocalDate desiredDate = LocalDate.now()
.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 1)
.with(ChronoField.DAY_OF_WEEK, 1)
.withYear(2018);
Which results in 2018-01-02 and it should be 2018-01-01. How is this possible?
The order of invoked methods seems matter.
It you invoke them by descending time-granularity (year, week of week and day of week), you get the correct result :
long weekNumber = 1;
long dayOfWeek = 1;
int year = 2018;
LocalDate desiredDate = LocalDate.now()
.withYear(year)
.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber)
.with(ChronoField.DAY_OF_WEEK, dayOfWeek );
System.out.println(desiredDate);
2018-01-01
Note that the problem origin comes from :
.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber)
that sets the week number (1 to 53) according to the current year.
The Java LocalDate API cannot adapt this value if then you change the year with .withYear(year) as the week number information is not kept in the LocalDate instance.
You can indeed see in LocalDate implementation that LocalDate instances are defined by only 3 field : year, month and day.
public final class LocalDate
implements Temporal, TemporalAdjuster, ChronoLocalDate, Serializable {
...
private final int year;
/**
* The month-of-year.
*/
private final short month;
/**
* The day-of-month.
*/
private final short day;
...
}
So to be precise, the important thing is that :
.withYear(year) be invoked before
.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber);
I want to mention, that there is another Problem(?) with LocalDate.
This Code does also create a wrong result:
int jahr = Integer.parseInt(str[0]);
int woche = Integer.parseInt(str[1]);
LocalDate year = LocalDate.of(jahr, 1, 1);
LocalDate week = year.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, woche);
LocalDate day = week.with(wochentag);
return day;
If you change the creation of the year variable to
LocalDate year = LocalDate.now().withYear(jahr);
the code returns the expected result. It seems as the way you construct a LocalDate matters. I guess the timezone is omitted in the ".of()" version.
I'm writing a java program and I have been stuck for quite some while with all the Date, DateTime and so forth parts of Java Programming.
What I want is to have a DATE object only. I have a class:
Deployment.java
public class Deployment {
int id;
LocalDate deviceDeploymentDate; //I'm unsure what this should be
public Deployment(int id, LocalDate deviceDeploymentDate) {
this.id = id;
this.deviceDeploymentDate = deviceDeploymentDate;
}
public Deployment() {
}
public LocalDate getDeviceDeploymentDate() {
return deviceDeploymentDate;
}
public void setDeviceDeploymentDate(LocalDate date) {
this.deviceDeploymentDate = date;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
And I have a Date Picker in my GUI.
From this Date Picker I can get the date in a string format (and also change it to int year, int month and int date if needed ofc). From this I want to store some sort of DATE within my Deployment object, and I do not want the time to be part of this at all.
Question
Which datatype should I use to do this? And how would I do?
Misc
I have shortly looked at Joda Time, but have been unable to create a LocalDate / DateTime type from either the String or integers that I can get from the Date Picker.
Joda-Time is great, but is mostly not needed since the Date-Time API in Java 8 and later. The team behind Joda-Time even advices users on Java 8 or above to use the standard API:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
Given this, you should use LocalDate from the standard API, java.time. Your Deployment class can look just like it does now, just make sure to import the correct package (java.time.LocalDate).
Since you have access to the fields (year, month and day), you can use one of the of() methods in the API:
LocalDate.of(year, month, day);
Note that month and day starts with 1, i.e. January is month 1. In the previous Date/Calendar APIs, month counting started with 0, i.e. January was month 0. In other words, be careful if you mix the two APIs.
By the way, java.time has a predefined Month enum that might be handy instead of using integers for months:
LocalDate localDate = LocalDate.of(2012, Month.January, 31);
You can keep using LocalDate(as per David's comment) and use DateTimeFormatter from Joda Time as below to convert String into LocalDate.
final DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyy-MMM-dd");
final LocalDate dt = dtf.parseLocalDate(yourinputString);
In Java, how would I go about constructing a utility that would take a range of dates (start and end date) and then would see how many times a given partial date ( the month and day-of-month) appears in that range, and will add an entry to a list for each match.
In my instance, I want to give it a range of say 5 years - starting Jan 1st 2014 and going to Dec 31st 2019. My check date is the 2nd August. I want the method to return the full information about each match of any August 2 of any year in the range. So for 2014 is will return Saturday 2nd August 2014, then Sunday 2nd August 2015 etc and so on.
I've been trying to get something working so far with Joda Time and the default date/calendar classes in Java and I'm just getting myself in a mess.
Thanks,
S
Edit: How silly of me, apologies for not adding my code :(
public static List<Date> getDaysInRange(Date startdate,
Date enddate,
Date checkDate) {
SimpleDateFormat sdf = new SimpleDateFormat("MMdd");
List<Date> dates = new ArrayList<>();
Calendar cal = new GregorianCalendar();
cal.setTime(startdate);
while (cal.getTime().before(enddate)) {
if (sdf.format(cal.getTime()).equals(sdf.format(checkDate))) {
Date result = cal.getTime();
dates.add(result);
}
cal.add(Calendar.DATE, 1);
}
return dates;
}
Date-Only
Since you want only a date without time-of-day and without time zone, use a date-only class. The old java.util.Date/.Calendar classes lack such a class. And those old classes are notoriously troublesome and flawed.
Instead use either:
Joda-Time
java.time, built into Java 8, inspired by Joda-Time.
Joda-Time
Here is some untested code using Joda-Time 2.6.
The main idea is to focus on the small set of possible year numbers rather than test every day of year. In the example below, that means six date-time values to compare rather than thousands. Besides efficiency, the purpose of the code becomes more apparent.
The arguments to your routine should be a month number and a day-of-month number, a pair of ints or Integers, rather than a Date. As seen in this examples two int variables, month and day.
LocalDate start = new LocalDate( 2011, 2, 3 );
LocalDate stop = new LocalDate( 2016, 4, 5 );
int yearStart = start.getYear();
int yearStop = stop.getYear();
int month = 11;
int day = 22;
for ( i = yearStart, i <= yearStop, i++ )
{
LocalDate x = new LocalDate( i, month, day );
boolean matchStart = ( x.isEqual( start ) || x.isAfter( start ) );
boolean matchStop = x.isBefore( stop ); // Half-Open approach where beginning of range is inclusive while ending is exclusive.
if ( matchStart && matchStop )
{
// Add to collection of LocalDate objects.
// Later you can ask each LocalDate object for its day-of-week.
{
}
java.time
The java.time package also offers a LocalDate class. The code would be similar to the above Joda-Time example.
I think using SimpleDateFormat is a bad idea. Use Calendar for comparison directly, like this
cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH) && cal1.get(Calendar.DAY_OF_MONTH) == cal2.get(Calendar.DAY_OF_MONTH)