This question already has answers here:
How to check if 2 dates are on the same day in Java
(4 answers)
Closed 8 years ago.
I have two calendar objects, they seems to contain same dates but the compareTo() method is returning -1 as result, Can any one explain the reason behind this.
On debugging the two Calendar objects, the result is shown as :
2014-06-01T00:00:00.000Z
for both calendar objects but the compareTo() is returning -1. Even the long time in millis for both dates are different.
Well, have a look at the Calendar code (this is from JDK 1.7.0-13):
public int compareTo(Calendar anotherCalendar) {
return compareTo(getMillisOf(anotherCalendar));
}
private int compareTo(long t) {
long thisTime = getMillisOf(this);
return (thisTime > t) ? 1 : (thisTime == t) ? 0 : -1;
}
It should be obvious that if the two Calendar's have different millis, then they're different as per the second method.
In any case, the millis in your example should not both represent 2014-06-01T00:00:00.000Z so there's another problem in your code. Try this:
Timestamp ts1 = new Timestamp( 1401561000000L );
Timestamp ts2 = new Timestamp( 1401595200000L );
System.err.println( ts1 );
System.err.println( ts2 );
Outputs:
2014-05-31 20:30:00.0
2014-06-01 06:00:00.0
Cheers,
The milliseconds number is the "offical" time in Java. However, for a variety or reasons, there are numbers with the same date/time which have different numbers of milliseconds. Then normal reason is clock adjustments. E.g. Sometimes you have to add a second or two to account for irregularities in the earth's orbit. The other big source is when regions were first brought into the UTC, then some time zones moved hours.
THere is also the common source for these things: DST.
This will happen twice a year when you move to daylight saving time, on the one hand there are date/times which do not exists, as they were "skipped", and there are other times which happened twice, as the clock gets reset at midnight, so 11pm-midnight happens twice on the same day.
If you want to just compare the minutes and ignore the milliseconds or seconds do this:
You need to use
cal.set(Calendar.MILLISECOND, 0);
and possibly as well
cal.set(Calendar.SECOND, 0);
if you just need the minutes to match.
Quick explanation of what is going on:
The JavaDoc for Calendar states:
Compares the time values (millisecond offsets from the Epoch)
represented by two Calendar objects.
So you acknowledge that ".. long time in millis for both dates are different .."
#JonSkeet says in this question:
Calendar.setTime takes a java.util.Date, which is just a wrapper
around a long indicating the number of milliseconds since midnight Jan
1st 1970, UTC. It's not "in the format MM/dd/yyy" - that's a string
representation, not a java.util.Date. If it happens to print something
out in the format MM/dd/yyyy, that's just what Date.toString is doing
for you - it's not inherently part of the format.
This should answer your question about what is going on.
Note: java.util.Date has the same problem.
PS. A lot of people say use Joda Time, which I have heard is going to be in Java 8, but I have not personally tried it. If you are going to be using a lot of date code, I'd recommend you use it.
I invoked compareTo on Date instead of Calendar and got the correct result. It might be because of the fact that Calendar stores Timezone information but Date object does not.
Thanks
Related
This question already has an answer here:
How can I return LocalDate.now() in milliseconds?
(1 answer)
Closed 2 years ago.
I need to know how to get LocalTime to milliseconds
LocalTime lunchTime = LocalTime.parse("01:00:00",
DateTimeFormatter.ISO_TIME);
If i am going to execute lunchTime.getMinute() i only get 0 and lunchTime.getHour() i only get 1 as an hour. How to get value in milliseconds?
Try getting nano seconds or seconds and converting to milliseconds (depending on what precision you're dealing with).
lunchTime.toNanoOfDay() / 1e+6
lunchTime.toSecondOfDay() * 1e+3
If you want the millisecond of the day (in other words the count of milliseconds since 00:00), there is a ChronoField enum constant exactly for that:
LocalTime lunchTime = LocalTime.parse("01:00:00");
int millisecondOfDay = lunchTime.get(ChronoField.MILLI_OF_DAY);
System.out.println("Lunch is at " + millisecondOfDay + " milliseconds of the day");
Output:
Lunch is at 3600000 milliseconds of the day
(1 AM is probably a funny time for lunch for some, but for the sake of demonstration and of using your own example.)
The date and time classes of java.time generally have got a get method that accepts a TemporalField argument. LocalTime is no exception to this rule. The most common thing to do when calling get() is to pass a ChronoField constant. The method is very versatile for getting values from the date-time object for which no getXxx method is provided.
Doc link: ChronoField.MILLI_OF_DAY
You can use System.currentTimeMillis(), refer https://currentmillis.com/
Also, please refer https://stackoverflow.com/a/26637209/1270989 to followup on parsing date in your choice of format.
Also, if you trying to get local time in your timezone from an application running in different timezone please follow comment https://stackoverflow.com/a/319398/1270989
I was hoping to squeeze a tiny performance gain out of many calls to a function that returns a timestamp. The function looks like this:
public static long get_now_ms(){
// returns number of MILLISECONDS since epoch
java.util.Date d = new java.util.Date();
return d.getTime();
}
Can I just replace this with:
public static long get_now_ms(){
// returns number of MILLISECONDS since epoch
return System.currentTimeMillis();
}
I know that Date internally uses System.currentTimeMillis(). My question is more whether or not daylight savings time or time zone could ever lead to a difference in result with these two approaches. I imagine this may come up with Calendar objects, but not Date objects, but would love some clarification on this.
I know I will likely not see an appreciable difference in performance in a real-world application, but would nevertheless like to know the answer.
Thanks!
No difference, except for the very slight lag caused by allocating a Date object.
From the javadoc the the default constructor of Date:
Allocates a Date object and initializes it so that it represents the time at which it was allocated, measured to the nearest millisecond.
A Date is just a thin wrapper around the epoch milliseconds, without any concept of timezones. Only when rendered to a String is timezone considered, but that is handled by the Locale class.
I would suggest running a unit test (ex. https://gist.github.com/ledlogic/8532028). I saw only a slight overall benefit to running the System.currentTimeMillis versus the (new Date()).getTime().
1 billion runs: (1000 outer loops, 1,000,000 inner loops):
System.currentTimeMillis(): 14.353 seconds
(new Date()).getTime(): 16.668 seconds
Individual runs would sometimes be slightly biased toward the later approach - depending on your system activity.
No difference, and Calendar.getTimeInMillis() is also same. because the return results is the number of milliseconds since January 1, 1970, 00:00:00 GMT. you will get a same long value whereever you are all over the word.
i am trying Joda time in java using the latest version 2.2 i have written a small snippet here is my code
public static void main(String[] args)
{
BoilerTester clazz = new BoilerTester();
Calendar today = Calendar.getInstance();
Calendar born = Calendar.getInstance();
//when returns 0 is 10363 when returning 1 = 10362 just a millisecond what have to do with days??
System.out.println(Math.abs(today.getTimeInMillis()-born.getTimeInMillis()));
born.set(1984,10,20);
clazz.compute(born,today);
}
private void compute(Calendar born, Calendar today)
{
System.out.println("JODA: " + org.joda.time.Days.daysBetween(new org.joda.time.DateTime(born.getTime()),new org.joda.time.DateTime(today.getTime())).getDays());
}
when i run the source code i am getting this values
JODA: 10363
later I run the same code and I am getting
JODA: 10362
Yes i have run maybe 2 or 3 times the same code to get different values but why this???
thanks a lot.
My guess is that sometimes, the today and born dates are on the exact same millisecond, and sometimes they differ by a few milliseconds (the time that elapses between the first call to Calendar.getInstance() and the second one). Since getDays() returns the number of complete days, a few milliseconds could make a difference.
I was writing my answer but JB Nizet was faster (he is absolutely right on what is happening). If you want to get rid of this kind of problems, you should leverage the concept of partial in joda-time:
A partial in Joda-Time is a partial date and time representation. All implementations represent local dates and times, and do not reference a time zone. As such, they only partially represent a date or time in the datetime continuum.
For example, with a LocalDate:
LocalDate born = new LocalDate(1984, 11, 20); // BE CAREFUL!: months in JDK are 0-11, but in Joda-Time are 1-12
System.out.println(Days.daysBetween(born, LocalDate.now()).getDays());
With this "partial" representation, you are not using hours, minutes, seconds or milliseconds internally, so you cannot face this problem due to milliseconds.
You're running a mix of JDK and Joda -- don't do that -- Joda replaces the JDK time classes completely.
So I'm using JodaTime in an app I've got and I need a way to tell if the current time is within 6 hours of midnight. Well actually I need to know if the time is within 8 hours of 2am, but JodaTime seems to provide a constant for midnight so I was looking at that. Anyway, I've tried a number of different things but nothing quite works. Any help or pointers would be appreciated.
This can be accomplished simply by using JodaTime without any math involved.
DateTime time = new DateTime(DateTimeZone.UTC);
Period period = new Period(time, time.plusDays(1).toDateMidnight());
System.out.println(period.getHours());
The time.plusDays(1).toDateMidnight() (yes, I was lazy), is so that I'm comparing with the next midnight, and not with today's midnight (which already passed).
If you want to check both before and after, just check both periods.
I would suggest using a DateTime object.
DateTime date = new DateTime();
int i = getSecondOfDay();
Then using a little math we can find the number of seconds 6pm would be.
18hours*60min*60seconds= 64800 seconds.
if ( i > 64800 ){
// Do what you need here
}
I assumed you needed to tell if it was 8 hours of am of this current day and not a specific day.
This is a bit hardcoded and pcalcao's answer is probably more flexible:
private static boolean isLessThan8HoursFrom2AM(DateTime date) {
return (date.getHourOfDay() >= 18 || date.getHourOfDay() < 10);
}
You can also check if the time of day is 6 hours from midday.
if(Math.abs(timeOfDay - 43200) >= 21600) // first or last 6 hours of day.
Given a any unix timestamp (i.e. 1306396801) which translates to 26.05.2011 08:00:01, how can I determine if this is within a given timeframe (i.e. 08:00:00 and 16:00:00)?
This needs to work for any day. I just want to know if this timestamp is within the given time-interval, on any future (or past) day, the date is unimportant. I don't care if it is on the 25th or 26th, as long as it is between 08:00 and 16:00.
I am on the lookout for a java solution, but any pseudo code that works will be ok, I'll just convert it.
My attempts so far has been converting it to a java Calendar, and reading out the hour/min/sec values and comparing those, but that just opened up a big can of worms. If the time interval I want it between is 16.30, I can't just check for tsHour > frameStartHour && tsMin > frameStartMin as this will discard any timestamps that got a minute part > 30.
Thank you for looking at this :)
To clarify.
I am only using and referring to UTC time, my timestamp is in UTC, and the range I want it within is in UTC.
I think I understand what you want. You want to test for any day, if it's between 8am and 4pm UTC. Take the timestamp mod 24*3600. This will give you the number of seconds elapsed in the day. Then you just compare that it's between 8*3600 and 16*3600. If you need to deal with timezones, things get more complicated.
Given your timestamp (in seconds) and the desired time zone, Jodatime gives you the hour which leads you to a simple integer range check.
new org.joda.time.DateTime(timestamp*1000L, zone).getHourOfDay()
With java.util.* its more difficult.
If I understood you correctly, you only need to normalize your dates to some common value. Create three instances of Calendar - one with your time, but day, month, and year set to zero, and two with start and end of your timeframe, other fields also zeroed. Then you can use Calendar.after() and Calendar.before() to see if the date is within the range.
Your unix timestamp is an absolute time. Your time frame is relative. You need some kind of time zone information in order to solve this problem. I just answered some of this for PostgreSQL a few minutes ago. Hopefully that article is of use.
Convert the beginning of your range to a unix timestamp, and the end of your range to a unix tmestamp, then it's a simple integer check.