how to set DATE using constructor?
public Date(int day, int month, int year)
{
this.day=day; // set day to 1-31
this.month=month; // set month to 1-12
this.year=year; // set year to 1900-9999
}
if i use
if(day<=1 || day >=31)
this.day=day;
else if(month<=1 || month>=12)
this.month=month;
else if(year<=1900 || year>=9999)
this.year=year
the problem is if I do this it will only result to 0 however if I removed the conditional statements the day will accept until 32 and months will be accept 13 up and so on
Well, you tell me. What do you want to happen? Here are some common options:
(recommended): Decree that a given date that clearly cannot exist, is not a legal invocation of the constructor. In other words, new Date(32, 2, 2051) isn't valid. To do that, throw an exception. For example:
if (day > 31) throw new IllegalArgumentException("Days must be between 1 and 31, inclusive");
Use rollover behaviour, and round off years. This is a 'I don't care it makes no sense do SOMETHING and just don't crash' attitude, and is not recommended. For example, you'd make that date as above act like march 4th, 2051.
Something else of your choosing. You are the programmer, after all.
Note that you are reinventing a very common wheel, and thus, unless this is homework or a pure learning exercise ('pure' in the sense of: This code will be tossed in the garbage once you have completed it), it is a mistake. use LocalDate instead.
NB: Dates are HARD. Harder than you think.
You don't have to create date attributes for holding date information. You can just use either java 8 LocalDate or Date API . LocalDate is thread safe and immutable, most recommended way of handling date use cases.
If you insist on creating your own Date class you can just easily do the following.
import java.time.*;
public class Date {
final LocalDate date;
public Date(int day, int month, int year) {
date = LocalDate.of(year, month, day);
}
public int getYear() {
return date.getYear();
}
public Month getMonth() {
return date.getMonth();
}
public int getDay() {
return date.getDayOfMonth();
}
}
Using the Date class.
public class Main {
public static void main(String[] args) {
try{
Date date1 = new Date(2020, 13, 33);
} catch(DateTimeException ex){
System.out.println("Invalid input");
}
}
}
Related
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.
I would like to store Date with optional month and day in java.
I know of the java.time.LocalYear to store just the year.
Shall I create my own custom class to hold dates with optional month and day or are there any custom library to solve the problem.
public class Date {
private LocalYear year;
private int month;
private int day;
public Date(LocalYear year) {
this.year = year;
}
public Date(LocalYear year, int month) {
this.year = year;
this.month = month;
}
public Date(LocalYear year, int month, iny day) {
this.year = year;
this.month = month;
this.day = day;
}
}
It’s hard to guide you without knowing your use case. One option is using the TemporalAccessor interface as a common type for dates with and without month and/or day of month and then put either a LocalDate, a YearMonth or a Year into your variable (the last class is just called Year (not LocalYear, though it would have been in line with the naming scheme)). For example:
List<TemporalAccessor> dates = List.of(
LocalDate.of(2019, Month.OCTOBER, 3), // full date
YearMonth.of(2019, Month.NOVEMBER), // no day of month
Year.of(2020)); // no month or day of month
What can we use this for? One example:
for (TemporalAccessor ta : dates) {
System.out.println(ta);
System.out.println("Year: " + ta.get(ChronoField.YEAR));
if (ta.isSupported(ChronoField.MONTH_OF_YEAR)) {
System.out.println("Month: " + ta.get(ChronoField.MONTH_OF_YEAR));
} else {
System.out.println("Month: undefined");
}
if (ta.isSupported(ChronoField.DAY_OF_MONTH)) {
System.out.println("Day: " + ta.get(ChronoField.DAY_OF_MONTH));
} else {
System.out.println("Day: undefined");
}
System.out.println();
}
This outputs:
2019-10-03
Year: 2019
Month: 10
Day: 3
2019-11
Year: 2019
Month: 11
Day: undefined
2020
Year: 2020
Month: undefined
Day: undefined
Whether or how well it fulfils your requirements I cannot tell.
Using ChronoField constants for access is low-level, so you may want to wrap the TemporalAccessor in a nice class with nice getters. For example:
public class PartialDate {
private TemporalAccessor date;
public PartialDate(Year year) {
date = year;
}
public PartialDate(Year year, int month) {
date = year.atMonth(month);
}
public PartialDate(Year year, int month, int day) {
date = year.atMonth(month).atDay(day);
}
public Year getYear() {
return Year.from(date);
}
public OptionalInt getMonthValue() {
if (date.isSupported(ChronoField.MONTH_OF_YEAR)) {
return OptionalInt.of(date.get(ChronoField.MONTH_OF_YEAR));
} else {
return OptionalInt.empty();
}
}
// A similar getDay method
}
You may extend the class to your needs. Maybe you want constructors that accept a Month enum constant and/or a YearMonth object directly and/or getters that return those types wrapped in Optionals.
Link: Oracle tutorial: Date Time explaining how to use java.time.
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 written a java program which will return date, month and year
(datatype int)
import java.util.*;
class DateTime {
int day,month,year;
GregorianCalendar date = new GregorianCalendar();
public DateTime () {
public int TimeT() {
day = date.get(Calendar.DAY_OF_MONTH);
month = date.get(Calendar.MONTH);
year = date.get(Calendar.YEAR);
// return day;
}
}
I am really confuse how to return day, month and year.
I have to return it, so I can use it many times.
Define a type to encapsulate the three attributes, and change method return type to that class, like this:
public class YearMonthDay {
private final year;
private final month;
private final day;
public int getYear() {return year;}
public int getMonth() {return month;}
public int getDay() {return day;}
public YearMonthDay(int y, int m, int d) {
year = y;
month = m;
day = d;
}
// Consider overriding toString, and optionally hashCode and equals
}
Now you can change your class to return YearMonthDay:
public YearMonthDay TimeT(){
return new YearMonthDay(
date.get(Calendar.YEAR)
, date.get(Calendar.MONTH)
, date.get(Calendar.DAY_OF_MONTH)
);
}
A caller can now obtain the YearMonthDay once, and then access its properties from multiple places.
I think I may see what you are trying to say. 'Braj' had the right idea in the code he offered. However, I am not sure if that fully answers your needs or not. I am unsure as to whether you want to return each value (day, month, year) separately, or all together using one method? I will try my best regardless.
Below I will show you the code for DateTime:
import java.util.GregorianCalendar;
class DateTime {
private int day, month, year;
GregorianCalendar date = new GregorianCalendar();
public DateTime() {
day = date.get(GregorianCalendar.DAY_OF_MONTH);
month = date.get(GregorianCalendar.MONTH) + 1;
year = date.get(GregorianCalendar.YEAR);
}
public DateTime(int day, int month, int year){
this.day = day;
this.month = month;
this.year = year;
}
// Accessors ///
public int getDay(){
return day;
}
public int getMonth(){
return month;
}
public int getYear(){
return year;
}
// Mutators ///
public int setDay(){
return day;
}
public int setMonth(){
return month;
}
public int setYear(){
return year;
}
// String ///
public String toString(){
return getMonth() + "/" + getDay() + "/" + getYear();
}
}
Now to explain.
I made the day, month, and year private to begin with and kept your default constructor practically the same except for one thing.
I added 1 to the month because months January - December are indexed at 0 - 11 rather than 1 - 12. This means your month wouldn't follow conventional means. I never knew something such as the GregorianCalendar existed in java's import libraries, so I was initially confused for a couple of seconds when I tested my code.
Moving on I made an additional constructor in case you ever wanted to input your own dates for whatever reason. If you do not plan on making separate DateTime objects to hold random dates, then this is completely unnecessary.
Afterwards I made several accessors - getDay(), getMonth(), getYear() - in case you ever needed to grab the specific aspect of the date.
To finish it off I made a toString() method to print out your DateTime's day month and year all in one String in a conventional format.
If you don't want to change the individual aspects of the date (such as the day, the month, or the year) I'd recommend getting rid of the 'Mutators'. If you don't want to access the individual aspects of the date, then I'd recommend getting rid of the 'Accessors'.
NOW, if for some reason, you want to be able to edit and access the date's components inside your CLIENT, then you should not make the instances of day, month, and year private, but instead public.
Here is the code for the DateTime class that will allow you to change the values inside the CLIENT. (I don't recommend this. I suggest you get used to making accessors and mutators instead.) I decided to call it DateTime2:
import java.util.GregorianCalendar;
class DateTime2 {
public int day, month, year;
GregorianCalendar date = new GregorianCalendar();
public DateTime2() {
day = date.get(GregorianCalendar.DAY_OF_MONTH);
month = date.get(GregorianCalendar.MONTH) + 1;
year = date.get(GregorianCalendar.YEAR);
}
public DateTime2(int day, int month, int year){
this.day = day;
this.month = month;
this.year = year;
}
public String toString(){
return month + "/" + day + "/" + year;
}
}
I left the second constructor in there in case you still want to make separate DateTime2 objects with different dates...
And here if the client code that tests the two classes out, followed by the output:
CLIENT:
public class DateTime_CLIENT{
public static void main(){
DateTime dt = new DateTime();
System.out.println("- DateTime -");
System.out.println("Date: " + dt);
System.out.println("Month: " + dt.getMonth());
System.out.println("Day: " + dt.getDay());
System.out.println("Year: " + dt.getYear() + "\n");
DateTime2 dt2 = new DateTime2();
System.out.println("- DateTime2 -");
System.out.println("Date: " + dt2);
System.out.println("Month: " + dt2.month);
System.out.println("Day: " + dt2.day);
System.out.println("Year: " + dt2.year + "\n");
dt2.day = 400000;
System.out.println("- DateTime2 - CHANGE FROM CLIENT");
System.out.println("Date: " + dt2);
System.out.println("Month: " + dt2.month);
System.out.println("Day: " + dt2.day);
System.out.print("Year: " + dt2.year);
}
}
OUTPUT:
- DateTime -
Date: 7/16/2014
Month: 7
Day: 16
Year: 2014
- DateTime2 -
Date: 7/16/2014
Month: 7
Day: 16
Year: 2014
- DateTime2 - CHANGE FROM CLIENT
Date: 7/400000/2014
Month: 7
Day: 400000
Year: 2014
Hope this helped! ;D
Create different method for each one
public int getDay(Date date){
return date.get(Calendar.DAY_OF_MONTH);
}
public int getMonth(Date date){
return date.get(Calendar.MONTH);
}
public int getYear(Date date){
return date.get(Calendar.YEAR);
}
Create a class out of the three fields and return an object of this type.
Java can't actually return multiple values with a method. However, you can have your method return a string with the necessary information, then parse the string. Alternatively, create a daymonthyear object with all of the necessary attributes and return the object.
Use a HashMap:
public HashMap<String, Integer> TimeT() {
HashMap<String, Integer> dateMap = new HashMap<String, Integer>();
dateMap.put("day",date.get(Calendar.DAY_OF_MONTH));
dateMap.put("month",date.get(Calendar.MONTH));
dateMap.put("year",date.get(Calendar.YEAR));
return dateMap;
}
String In Standard Format, ISO 8601
If you want to return the date information as text, use the Joda-Time library or the new java.time package in Java 8 to convert a date-time value into a String using the format defined by the ISO 8601 standard.
Those two libraries use ISO 8601 format by default. Such as 2014-07-13T18:02:49+05:30:
String output = DateTime.now().toString(); // YYYY-MM-DDTHH:MM:SS.SSS+-00:00:00 format.
But it is best to specify a desired time zone rather than rely implicitly on the JVM's default time zone.
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
String output = DateTime.now( timeZone ).toString();
If you want just year, month, and date only, then use an alternate formatter rather than the default one. The following code produces a string like 2014-07-13.
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( timeZone );
DateTimeFormatter formatter = ISODateTimeFormat.date(); // YYYY-MM-DD formatter.
String output = formatter.print( now );
Pass DateTime Object
If instead of a string, you want the number values communicated to another object, then just pass the Joda-Time DateTime object. The receiving object can call methods on the DateTime such as getYear, getMonthOfYear, and getDayOfMonth. As a bonus, the receiving object will have additional information in its hands such as time zone.
The other answers are correct for the general case: Create a class or use a Collection to communicate multiple values as Java can return only a single item from a method. But in the specific case of date-time values, it seems silly to invent a class when we already have such classes at our disposal.
Avoid java.Util.Date and .Calendar
The java.util.Date and .Calendar classes are notoriously troublesome. Avoid them. Using Joda-Time as a replacement is quite common. The new java.time package in Java 8 is another replacement, and was inspired by Joda-Time.
LocalDate Class
Both Joda-Time and java.time offer a LocalDate class to represent the date-only without time-of-day and without time zone. You may want to use this class. Usually a date-time is better if doing any comparisons across time zones, as a day’s beginning and ending are defined by a time zone.
Best case is make a class with members year, month and day, initialized in the method an returned.
If only and int have to be used you could merge the data with bit operations.
year | (month << 16) | (day << 24)
Don't known if it's valid java.
Reading would be:
year = date & 0xffff;
month = (date >> 16) & 0xff;
day = (date >> 24) & 0xff;
This is more common in native language.
It saems like the Calendar class already has everything the OP requires. There is no need to place the returned values into a hashmap or array or anything else. In the OP code, there is no return statement, but he wants to be able to re-use the code. Below is a simple method that demonstrates what the Calendar class gives us. Any method that returns a Calendar object is giving us everything we need because we can pull out the required values using get.
public static void main(String[] args) {
int day,month,year;
GregorianCalendar date = new GregorianCalendar();
day = date.get(Calendar.DAY_OF_MONTH);
month = date.get(Calendar.MONTH);
year = date.get(Calendar.YEAR);
System.out.println("Day:" + day);
System.out.println("month:" + month);
System.out.println("year:" + year);
}
Keep it simple. Return either the Date object (it contains everything you need) or an ISO string corresponding to this date in order to rebuild it later.
I recently discovered a difference between Oracle adds months to a given date (using ADD_MONTHS function) and the way Java adds months to a Calendar object.
For instance in oracle:
select add_months('2009-02-28', +1) from dual;
produced the result: "09-03-31"
And the query:
select add_months('2009-02-28', -1) from dual;
Produces the result "09-01-31"
However in Java, the results of the same calculations (using GregorianCalendar.add() method) are (respectively):
09-03-28
and
09-01-28
Is there some way to make Oracle and Java behave the same? (e.g. some setting in oracle or some parameter in Java)?
When you do month arithmetic you need to decide, from the business point of view, what is the right way to deal with months with differing numbers of days. The flip side to the issue you raised is what happens when going from a longer month, like August, to a shorter one like February (and even from Feb to Feb if leap years are involved).
If you are happy for errors to be reported because the calculation cannot find 'Feb-30', then look at INTERVAL
You can create own DateService class like bellow and use "addMonthToDateLikeOracle" method.
package db;
import org.joda.time.LocalDate;
import java.util.Calendar;
import java.util.Date;
public class DateService {
public static Date addMonthToDateLikeOracle(Date date, int months) {
Calendar c = Calendar.getInstance();
c.setTime(date);
Date retval;
if (DateService.isLastDayOfMonth(date)) {
c.add(Calendar.MONTH, 1);
c.add(Calendar.MONTH, 1);
c.set(Calendar.DATE, 1);
c.add(Calendar.DATE, -1);
retval = c.getTime();
} else {
retval = LocalDate.fromDateFields(date).plusMonths(months).toDate();
}
return retval;
}
public static boolean isLastDayOfMonth(Date date) {
if (date == null) {
throw new RuntimeException("The date parameter cannot be null!");
}
Date endOfMonth = getEndOfMonth(date);
return endOfMonth.equals(date);
}
public static Date getEndOfMonth(Date date) {
Date startOfMonth = getStartOfMonth(date);
Date startOfNextMonth = LocalDate.fromDateFields(startOfMonth).plusMonths(1).toDate();
return LocalDate.fromDateFields(startOfNextMonth).plusDays(-1).toDate();
}
public static Date getStartOfMonth(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.DAY_OF_MONTH, 1);
return calendar.getTime();
}
}
From the Oracle reference on add_months (http://download-west.oracle.com/docs/cd/B19306_01/server.102/b14200/functions004.htm)
If date is the last day of the month or if the resulting month has fewer days than the day component of date, then the result is the last day of the resulting month. Otherwise, the result has the same day component as date.
That means you're going to have to write a method for Java that performs the same check to get the same results (or a function in PL/SQL that behaves the same as Java).
You could write your own add months function in java.
public Date functionAddMonth(Date d, int month)
{
Calendar c = Calendar.getInstance();
c.setTime(d);
c.add(Calendar.DAY, 1);
c.add(Calendar.MONTH, month);
c.add(Calendar.DAY, -1);
return c.getTime();
}