I am using Joda DateTime and have 2 dates :
DateTime old //which is 1:46PM
DateTime new //which is 6:46PM
note: excluded the dates.
How may i be able to loop through the difference in this order :
(print a message for the first half hour, another message for the next 30 minutes and another message per subsequent hour) ?
I was thinking of Subtracting the old date from the new date then make a loop but i don't get the logic. Any pointers will be helpful.
example
If i subtract both times above, i will have an elapsed time of 5 hours.
Loop 5 hours
{
for the first hour (print this)
next 30minutes (print that)
every subsequent hour (print ....)
}
I would use the type LocalTime instead. If you have DateTime as input then please convert it using the method toLocalTime() (with same time and chronology and timezone).
LocalTime start = new LocalTime(13, 46);
LocalTime end = new LocalTime(18, 46);
LocalTime current = start;
for (int i = 0; current.isBefore(end); i++) {
// code your print action here
current = current.plusMinutes((i < 2) ? 30 : 60);
}
Then you get an action for following times:
13:46
14:16
14:46
15:46
16:46
17:46
Related
This question already has answers here:
How to get milliseconds from LocalDateTime in Java 8
(14 answers)
Closed 3 years ago.
Executed piece of code :
String lapTime = "27:10.190";
int minutes = Integer.parseInt(lapTime.substring(0, lapTime.indexOf(":")));
int seconds = Integer.parseInt(lapTime.substring(lapTime.indexOf(":")+1, lapTime.indexOf(".")));
int milliseconds = Integer.parseInt(lapTime.substring(lapTime.indexOf(".")+1));
LocalTime localTime = LocalTime.of(0, minutes, seconds, milliseconds);
How to gain number of milliseconds of LocalTime localTime = LocalTime.of(0, minutes, seconds, milliseconds); ?
TL;DR Use Duration, not LocalTime. See end of answer.
Question code is incorrect
Be aware that the 4th argument to LocalTime.of() is nanosecond, not millisecond, which you'd see if you print localTime:
System.out.println(localTime); // prints: 00:27:10.000000190
So you need to change your code to:
LocalTime localTime = LocalTime.of(0, minutes, seconds, milliseconds * 1000000);
System.out.println(localTime); // prints: 00:27:10.190
Using LocalTime
If you wanted the milliseconds value back, call getLong(TemporalField field) with ChronoField.MILLI_OF_SECOND:
localTime.getLong(ChronoField.MILLI_OF_SECOND) // returns 190
To gain total number of milliseconds, i.e. not just the milliseconds value, use ChronoField.MILLI_OF_DAY as argument:
localTime.getLong(ChronoField.MILLI_OF_DAY) // returns 1630190
Using Duration
However, since the input is named lapTime, the LocalTime class is not the right tool for the job. E.g. your code will fail if minutes >= 60.
The right tool is the Duration class, e.g.
Duration duration = Duration.ofMinutes(minutes).plusSeconds(seconds).plusMillis(milliseconds);
Or:
Duration duration = Duration.ofSeconds(seconds, milliseconds * 1000000).plusMinutes(minutes);
You can then get the milliseconds directly by calling toMillis():
duration.toMillis(); // returns 1630190
That works even if the lap time exceeds one hour, e.g.
String lapTime = "127:10.190";
. . .
duration.toMillis(); // returns 7630190
In Java 9+, you can get the millisecond part back easily, by calling toMillisPart():
duration.toMillisPart(); // returns 190
To get the number of milliseconds within the second, you can do localTime.get(ChronoField.MILLI_OF_SECOND).
You can do localTime.toNanoOfDay() / 1000000 to get the number of milliseconds since the start of the day.
Since a LocalTime has no day or date associated with it, you can't directly get milliseconds-since-the-epoch.
You can attach a LocalDate to a LocalTime using LocalTime.atDate to get a LocalDateTime. Then you can call atZone, atOffset or toInstant to get an object that can return epochMillis.
I want to compare if 2 LocalTime are equal, but only using the hours, minutes and seconds, not with all the data of the variable, like milliseconds.
How can I accomplish that?
Considering the last edited version of your question, you can compare two instances of LocalTime by just hour, minute and second part this way:
LocalTime lt1 = LocalTime.now(); // usually contains seconds and subseconds
LocalTime lt2 = LocalTime.of(22, 48); // example with zero second part
boolean isEqualInSecondPrecision =
lt1.truncatedTo(ChronoUnit.SECONDS).equals(lt2.truncatedTo(ChronoUnit.SECONDS));
You can set the hours to the same in both with myTime.withHour(0), than you have left only the minutes and seconds that differ and you are able to come these 2 times.
Example:
time1 = ...
time2 = ...
if (time1.withHour(0).equals(time2.withHour(0))) {
System.out.println('Minutes and Seconds of time1 and time2 are equal!');
}
You can just set both nanos to one number to make them the same with each other, say, zero, to compare them.
LocalTime localTime1 = LocalTime.of(1, 2, 3, 100);
LocalTime localTime2 = LocalTime.of(1, 2, 3, 47);
if (localTime1.withNano(0).equals(localTime2.withNano(0))){
System.out.println("something");
}
Something like this
LocalTime t1=..
LocalTime t2=..
LocalTime.of(t1.getHour(), t1.getMinutes()).compareTo(LocalTime.of(t2.getHour(),t2.getMinutes());
with also seconds if u need of course
I have a date and a number and want to check if this date and this number occurs in a list of other dates within:
+-20 date intervall with the same number
so for example 1, 1.1.2013 and 1,3.1.2013 should reuturn false.
I tried to implement the method something like that:
private List<EventDate> dayIntervall(List<EventDate> eventList) throws Exception {
List<EventDate> resultList = new ArrayList<EventDate>();
for (int i = 0; i < eventList.size(); i++) {
String string = eventList.get(i).getDate();
Date equalDate = new SimpleDateFormat("dd.MM.yyyy", Locale.GERMAN).parse(string);
for (int j = 0; j < eventList.size(); j++) {
String string1 = eventList.get(i).getDate();
Date otherDate = new SimpleDateFormat("dd.MM.yyyy", Locale.GERMAN).parse(string1);
if (check number of i with number of j && check Date) {
//do magic
}
}
}
return resultList;
}
The construction of the iteration method is not that hard. What is hard for me is the date intervall checking part. I tried it like that:
boolean isWithinRange(Date testDate, Date days) {
return !(testDate.before(days) || testDate.after(days));
}
However that does not work because days are not takes as days. Any suggestions on how to fix that?
I really appreciate your answer!
You question is difficult to follow. But given its title, perhaps this will help…
Span Of Time In Joda-Time
The Joda-Time library provides a trio of classes to represent a span of time: Interval, Period, and Duration.
Interval
An Interval object has specific endpoints that lie on the timeline of the Universe. A handy contains method tells if a DateTime object occurs within those endpoints. The beginning endpoint in inclusive while the last endpoint is exclusive.
Time Zones
Note that time zones are important, for handling Daylight Saving Time and other anomalies, and for handling start-of-day. Keep in mind that while a java.util.Date seems like it has a time zone but does not, a DateTime truly does know its own time zone.
Sample Code
Some code off the top of my head (untested)…
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Berlin" );
DateTime dateTime = new DateTime( yourDateGoesHere, timeZone );
Interval interval = new Interval( dateTime.minusDays( 20 ), dateTime.plusDays( 20 ) );
boolean didEventOccurDuringInterval = interval.contains( someOtherDateTime );
Whole Days
If you want whole days, call the withTimeAtStartOfDay method to get first moment of the day. In this case, you probably need to add 21 rather than 20 days for the ending point. As I said above, the end point is exclusive. So if you want whole days, you need the first moment after the time period you care about. You need the moment after the stroke of midnight. If this does not make sense, see my answers to other questions here and here.
Note that Joda-Time includes some "midnight"-related methods and classes. Those are no longer recommended by the Joda team. The "withTimeAtStartOfDay" method takes their place.
DateTime start = dateTime.minusDays( 20 ).withTimeAtStartOfDay();
DateTime stop = dateTime.plusDays( 21 ).withTimeAtStartOfDay(); // 21, not 20, for whole days.
Interval interval = new Interval( start, stop );
You should avoid java.util.Date if at all possible. Using the backport of ThreeTen (the long awaited replacement date/time API coming in JDK8), you can get the number of days between two dates like so:
int daysBetween(LocalDate start, LocalDate end) {
return Math.abs(start.periodUntil(end).getDays());
}
Does that help?
You can get the number of dates in between the 2 dates and compare with your days parameter. Using Joda-Time API it is relatively an easy task: How do I calculate the difference between two dates?.
Code:
SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy", Locale.GERMAN);
Date startDate = format.parse("1.1.2013");
Date endDate = format.parse("3.1.2013");
Days d = Days.daysBetween(new DateTime(startDate), new DateTime(endDate));
System.out.println(d.getDays());
Gives,
2
This is possible using Calendar class as well:
Calendar cal = Calendar.getInstance();
cal.setTime(startDate);
System.out.println(cal.fieldDifference(endDate, Calendar.DAY_OF_YEAR));
Gives,
2
This 2 can now be compared to your actual value (20).
Hello I have this excerpt of code:
end = new DateTime(mergeToDateTime(this.endDate, this.empEndTime));
Duration extraTime = new Duration(this.preTime.getTime()); //add the first 30 mins
extraTime = extraTime.plus(new Duration(this.postTime.getTime())); //add the second 30 mins
end = end.plus(extraTime); // extraTime = -3600?
When I look in the debugger my durations are always coming up negative. I have no idea why this is, even though according to the API, it is possible to create a duration out of the a long type, hence the getTime(). (preTime and postTime are java.sql.Time types)
I guess your instances of java.sql.Time were created in such a way that their millisecond values include timezone offset.
For example, deprecated java.sql.Time(int hour, int minute, int second) constructor takes offset of the current timezone into account:
System.out.println(new Time(1, 0, 0).getTime()); // Prints -7200000 in UTC+3 timezone
It looks like timezone offset is introduced by JDBC driver, and it can be easily compensated by converting java.sql.Time to LocalTime (and vice versa):
LocalTime lt = new LocalTime(time);
Then you can convert LocalTime to duration:
Duration d = new Duration(lt.getMillisOfDay());
Aren't you starting out wrong when you use an instant in time as duration? The constructor signature you are using is Duration(long duration), not Duration(long startInstant) -- there is no such constructor, in fact.
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.