This question already has answers here:
Java Calendar adds a random number of milliseconds?
(4 answers)
Closed 4 years ago.
I'm wondering why I always get a difference between this date in milliseconds.
Any idea ?
Here is the output :
date = 1572794103293 ms
date2 = 1572794103341 ms
date3 = 1572794103341 ms
date4 = 1572794103341 ms
and here is the code :
Date date = createDate();
Date date2 = createDate();
Date date3 = createDate();
Date date4 = createDate();
System.out.println(date.getTime());
System.out.println(date2.getTime());
System.out.println(date3.getTime());
System.out.println(date4.getTime());
private static Date createDate() {
Calendar c = GregorianCalendar.getInstance();
c.set(2019, Calendar.NOVEMBER, 03, 16, 15, 03);
return c.getTime();
}
In the documentation of Calendar.set, it is said :
Sets the values for the fields YEAR, MONTH, DAY_OF_MONTH, HOUR, MINUTE, and SECOND. Previous values of other fields are retained. If this is not desired, call clear() first.
The reason is that not all fields are set with this method, in you case, you don't have MILLISECOND set. So it keep the value when the instance was created.
The call of Calendar.clear will
Sets all the calendar field values and the time value (millisecond offset from the Epoch) of this Calendar undefined.
A quick example :
Calendar c = GregorianCalendar.getInstance();
c.clear();
c.set(2019, Calendar.NOVEMBER, 03, 16, 15, 03);
System.out.println(c.getTimeInMillis());
1572794103000
Milliseconds being undefined will give 0
In addition to the comments and AxelH's answer mentioning the fact that the milliseconds of a Calendar instance aren't changed by Calendar.set, there is still the curiosity that you get the same value for date2, date3 and date4, but a different value for date.
This is because the very first time you call createDate() the JVM has to initialize the Date class, which happens after Calendar c was initialized.
Thus on the first call c.getTime() needs more time than on the consecutive calls, which you can see as the difference between the value of date and the other 3 instances.
If you add a call to new Date() before the first call to createDate(), the difference between each value should be the same.
Please note that this does not fix your issue, it just hides it if your machine is fast enough. It's merely an explanation for the particular values you get.
Related
This question already has answers here:
Get yesterday's date using Date [duplicate]
(8 answers)
Closed 8 years ago.
I've got an object with a field timestamp with type java.sql.Timestamp;.
And I need to get objects with yesterday date from a collection.
How to get them?
I mean I need something like this
for(int i = 0; i < items.size(); i++) {
(if the items.get(i).date == yesterday_date)
(get object)
}
You can get yesterday's Date by following approach Answered by Jiger Joshi.
And by using new Timestamp(java.util.Date) you can get yesterday's timestamp, you should use Timestamp#equals to equaling two different timestamp.
if (items.get(i).date.equals(getYesterdaytimestamp())){
...
}
And there are something which you must consider while implementing this. Calender#getTime which returns Date object and date object contains date with time, so in that case your equaling date or timestamp must be exactly equals with yesterday's date and time.
If requirement is, it needs to equal just yesterday no not where time is not considerable fact. In that case you need to equals two timestamp after discarding time part.
if (equalsWithYesterday(items.get(i).date)){
...
}
...
public boolean equalsWithYesterday(Timestamp st){
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd"); // Time part has discarded
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1);
Date yesterday = dateFormat.parse(dateFormat.format(cal.getTime())); // get yesterday's Date without time part
Date srcDate = new Date(st);
Date srcDateWithoutTime =dateFormat.parse(dateFormat.format(srcDate));
return yesterday.equals(srcDateWithoutTime ); // checks src date equals yesterday.
}
You can convert the timestamp object to date object like this:
Date date = new Date(items.get(i).getTime());
or you can simply use method Timestamp#compareTo(Date o)
items.get(i).compareTo(yesterday_date);
I hope you are not interested to compare the time?
Simply use Calendar class to extract the day, month, year etc. from the date and simply compare it.
Use Calendar#get() method to get the specific field from the date object.
How to subtract one day from the current date?
// get Calendar with current date
Calendar cal = Calendar.getInstance();
// get yesterday's date
cal.add(Calendar.DATE, -1);
// get components of yesterday's date
int month = cal.get(Calendar.MONTH) + 1; // 0 for January, 1 for Feb and so on
int day = cal.get(Calendar.DATE);
int year = cal.get(Calendar.YEAR);
// get yesterday's date in milliseconds
long lMillis = cal.getTime().getTime();
The date is selected by the user using a drop down for year, month and day. I have to compare the user entered date with today's date. Basically see if they are the same date. For example
the user entered 02/16/2012. And if today is 02/16/2012 then I have to display a message. How do I do it?
I tried using milliseconds but that gives out wrong results.
And what kind of object are you getting back? String, Calendar, Date? You can get that string and compare it, at least that you think you'll have problems with order YYYY MM DD /// DD MM YYY in that case I suggest to create a custom string based on your spec YYYYMMDD and then compare them.
Date d1 = new Date();
Date d2 = new Date();
String day1 = d1.getYear()+"/"+d1.getMonth()+"/"+d1.getDate();
String day2 = d2.getYear()+"/"+d2.getMonth()+"/"+d2.getDate();
if(day1.equals(day2)){
System.out.println("Same day");
}
Dates in java are moments in time, with a resolution of "to the millisecond". To compare two dates effectively, you need to first set both dates to the "same time" in hours, minutes, seconds, and milliseconds. All of the "setTime" methods in a java.util.Date are depricated, because they don't function correctly for the internationalization and localization concerns.
To "fix" this, a new class was introduced GregorianCalendar
GregorianCalendar cal1 = new GregorianCalendar(2012, 11, 17);
GregorianCalendar cal2 = new GregorianCalendar(2012, 11, 17);
return cal1.equals(cal2); // will return true
The reason that GregorianCalendar works is related to the hours, minutes, seconds, and milliseconds being initialized to zero in the year, month, day constructor. You can attempt to approximate such with java.util.Date by using deprecated methods like setHours(0); however, eventually this will fail due to a lack of setMillis(0). This means that to use the Date format, you need to grab the milliseconds and perform some integer math to set the milliseconds to zero.
date1.setHours(0);
date1.setMinutes(0);
date1.setSeconds(0);
date1.setTime((date1.getTime() / 1000L) * 1000L);
date2.setHours(0);
date2.setMinutes(0);
date2.setSeconds(0);
date2.setTime((date2.getTime() / 1000L) * 1000L);
return date1.equals(date2); // now should do a calendar date only match
Trust me, just use the Calendar / GregorianCalendar class, it's the way forward (until Java adopts something more sophisticated, like joda time.
There is two way you can do it. first one is format both the date in same date format or handle date in string format.
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
String date1 = sdf.format(selectedDate);
String date2 = sdf.format(compareDate);
if(date1.equals(date2)){
}else{
}
Or
Calendar toDate = Calendar.getInstance();
Calendar nowDate = Calendar.getInstance();
toDate.set(<set-year>,<set-month>,<set-date->);
if(!toDate.before(nowDate))
//display your report
else
// don't display the report
Above answers are correct but consider using JodaTime - its much simpler and intuitive API.
You could set DateTime using with* methods and compare them.
Look at this answer
My program needs to represent this date as a java.sql.date object , but it seems that when I create a new date (using the calendar) and set it to '9999-12-31' and finally convert this java.util.date object to a java.sql.date object, this date is converted to something like '000-01-31'.
Calendar calendar = Calendar.getInstance();
calendar.set(9999, 12, 31);
infinityDate = new java.sql.Date(normalizeDate(calendar.getTime()).getTime());
infinityDate should be 31-12-9999
but when my code reaches here :
if(otherDate.equals(infinityDate))
{// Do stuff}
It never goes into the if condition as the infinityDate has for some reason been changed to 31-01-000, even though otherDate is infact '31-12-9999'.
The fact that otherDate is 31-12-9999 tells me that java can represent this dates , but for some reason , when I construct it using a calendar it changes the date. (otherDate comes from a jdbc statement which fetches data from a database)
This reference date '31-12-9999' has been fixed by some client , so it cannot be changed and my program has to be able to compare some incoming date values with this.
Does anyone know why this is happening , I realize that http://en.wikipedia.org/wiki/Year_10,000_problem may be a problem for dates after year 9999 , but I should be safe by a day.
EDIT : The Normalize date method only "normalizes the given date to midnight of that day"
private static java.util.Date normalizeDate(java.util.Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
date = calendar.getTime();
return date;
}
But , this issue was appearing before I was normalizing the date , I normalized it in an attempt to fix this.
Months are zero indexed. Use 11 for December, not 12. This is why you are rolling over the year.
Calendar.MONTH is zero-based. The call
calendar.set(9999, 12, 31);
sets the date to "the 31st day in the 13th month of the year 9999", which is then implicitly converted to the 1st month of the year 10000. It would result in an exception if you first called
calendar.setLenient(false);
Check hours, minutes, seconds and milliseconds that are held into these 2 date objects. I believe they are different.
If your want to compare the date (year, month, day) only you should probably create your custom Comparator and use it.
Consider the following code to only determine if the time component of one Date object is before the time component of another Date object:
private boolean validStartStopTime( Date start, Date stop ) {
Calendar startCal = Calendar.getInstance();
Calendar stopCal = Calendar.getInstance();
startCal.clear();
stopCal.clear();
startCal.setTime( start );
stopCal.setTime( stop );
startCal.set( Calendar.YEAR, 2011 );
stopCal.set( Calendar.YEAR, 2011 );
startCal.set( Calendar.MONTH, 1 );
stopCal.set( Calendar.MONTH, 1 );
startCal.set( Calendar.DAY_OF_YEAR, 1 );
stopCal.set( Calendar.DAY_OF_YEAR, 1 );
return startCal.before( stopCal );
}
Would this insure that time comparison is correct? Is there a better alternative (Joda is not an option)? I believe that this is equivalent to setting the Calendar objects to current date/time and manually copying over the hour, minutes, and milliseconds component. You can assume that timezone are the same.
EDIT: To clarify what I mean by comparing only the time component of a Date object. I mean that when looking specifically at the time portion, the start time is before the stop time. The date portion is ABSOLUTELY irrelevant (in that start="Jan 2 20011 10AM" and end="Jan 1 2011 11AM" is perfectly fine), if I had a choice I'd simply use something that contained just the time but a Date object is what I'm given. I'd like to not write a sequence of if-else which is why I have the approach above but I welcome a cleaner/better approach.
Your code should work fine. You could also format just the time components in a zero-based string notation and compare them lexicographically:
public static boolean timeIsBefore(Date d1, Date d2) {
DateFormat f = new SimpleDateFormat("HH:mm:ss.SSS");
return f.format(d1).compareTo(f.format(d2)) < 0;
}
[Edit]
This is assuming that the dates have the same timezone offset. If not you'll have to adjust them manually beforehand (or as part of this function).
There are 86,400,000 milliseconds in a day, why not just use that to figure it out?
You could just mod timeInMilliseconds with that number and compare the results.
I have a program that needs to start on 1/1/09 and when I start a new day, my program will show the next day.
This is what I have so far:
GregorianCalendar startDate = new GregorianCalendar(2009, Calendar.JANUARY, 1);
SimpleDateFormat sdf = new SimpleDateFormat("d/M/yyyy");
public void setStart()
{
startDate.setLenient(false);
System.out.println(sdf.format(startDate.getTime()));
}
public void today()
{
newDay = startDate.add(5, 1);
System.out.println(newDay);
//I want to add a day to the start day and when I start another new day, I want to add another day to that.
}
I am getting the error found void but expected int, in 'newDay = startDate.add(5, 1);'
What should I do?
The Calendar object has an add method which allows one to add or subtract values of a specified field.
For example,
Calendar c = new GregorianCalendar(2009, Calendar.JANUARY, 1);
c.add(Calendar.DAY_OF_MONTH, 1);
The constants for specifying the field can be found in the "Field Summary" of the Calendar class.
Just for future reference, The Java API Specification contains a lot of helpful information about how to use the classes which are part of the Java API.
Update:
I am getting the error found void but
expected int, in 'newDay =
startDate.add(5, 1);' What should I
do?
The add method does not return anything, therefore, trying to assign the result of calling Calendar.add is not valid.
The compiler error indicates that one is trying to assign a void to a variable with the type of int. This is not valid, as one cannot assign "nothing" to an int variable.
Just a guess, but perhaps this may be what is trying to be achieved:
// Get a calendar which is set to a specified date.
Calendar calendar = new GregorianCalendar(2009, Calendar.JANUARY, 1);
// Get the current date representation of the calendar.
Date startDate = calendar.getTime();
// Increment the calendar's date by 1 day.
calendar.add(Calendar.DAY_OF_MONTH, 1);
// Get the current date representation of the calendar.
Date endDate = calendar.getTime();
System.out.println(startDate);
System.out.println(endDate);
Output:
Thu Jan 01 00:00:00 PST 2009
Fri Jan 02 00:00:00 PST 2009
What needs to be considered is what Calendar actually is.
A Calendar is not a representation of a date. It is a representation of a calendar, and where it is currently pointing at. In order to get a representation of where the calendar is pointing at at the moment, one should obtain a Date from the Calendar using the getTime method.
If you can swing it requirement wise, move all your date/time needs to JODA, which is a much better library, with the added bonus that almost everything is immutable, meaning multithreading comes in for free.