I usually deal with dates with ints according to the pattern yyyyMMdd.
e.g.: today is 20170113, or better 20,170,113.
I need to calculate the distance bethween dates in days, so I wrote this:
public static int calculateDistance(int data1, int data2){
try {
SimpleDateFormat normalDateFormat = new SimpleDateFormat("yyyyMMdd");
long beginTime = normalDateFormat.parse(String.valueOf(data1)).getTime();
long endTime = normalDateFormat.parse(String.valueOf(data2)).getTime();
long diff = endTime - beginTime;
return (int) TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
} catch (ParseException e) {
e.printStackTrace();
return 0;
}
}
And this test:
public void testCalculateDistance() {
System.out.println(Calculator.calculateDistance(20090325, 20090328));
System.out.println(Calculator.calculateDistance(20090326, 20090329));
System.out.println(Calculator.calculateDistance(20090327, 20090330));
System.out.println(Calculator.calculateDistance(20090328, 20090331));
System.out.println(Calculator.calculateDistance(20090329, 20090401));
System.out.println(Calculator.calculateDistance(20090330, 20090402));
System.out.println(Calculator.calculateDistance(20090331, 20090403));
System.out.println(Calculator.calculateDistance(20090401, 20090404));
}
The output should always be the same, since I'm making the same modifications to both begin and end. But I get 2 (so 1 day less) iff the interval (end excluded) contains March 29.I also found it happens whenever I have this day of any year within the interval I mean to measure.
Why does it happen?
How can I fix it?
EDIT: I read this and I know how to calculate the difference between dates. The point is that this doesn't seem to work with this kind of classes, so this question is not a duplicate because I needn't know how to find the difference, but I need to know which classes I should use, instead of the ones I used to use.
In this case it is probably preferable to use LocalDate and ChronoUnit from java.time package.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate beginning = LocalDate.parse("20090325",formatter);
LocalDate ending = LocalDate.parse("20090328",formatter);
System.out.println(ChronoUnit.DAYS.between(beginning,ending));
Related
I have some Java code which returns the ISO-8601 time format from a given epoch time.
public String getISO8601(String epochTime) {
long epoch = Long.parseLong(epochTs);
ZoneId zone = ZoneId.of("Europe/London");
LocalDate then = Instant.ofEpochMilli(epoch).atZone(zone).toLocalDate();
LocalDate today = LocalDate.now(zone);
Period diff = Period.between(then, today);
return diff.toString();
}
When I pass epochTime to it: 1512259200000
This epoch time is: Sun 2017-12-03 00:00:00
So the method getISO8601 will return: P1Y
This is great! But is there any way I can make sure it will always and only return in days... for example: P365D (instead of: P1Y)
Unfortunately Period doesn't allow the units to be specified, but you can use the until method to handle this, specifying you want the difference in days:
public static Period getPeriodInDaysBetween(LocalDate from, LocalDate to) {
int days = (int) from.until(to, ChronoUnit.DAYS);
return Period.ofDays(days);
}
Use that instead of Period.between and it'll do what you want, I believe.
(The first line is equivalent to the ChronoUnit.DAYS.between(date1, date2) in MS90's answer. Use whichever you find more readable.)
Sure, take a look at following code:
public static long countDays(LocalDate date1, LocalDate date2) {
long daysInAPeriod = ChronoUnit.DAYS.between(date1, date2);
return daysInAPeriod;
}
Period has a getDays method which returns an int number of days in the Period.
In my app I create an object that represents a high school class. This object holds 2 Calendar objects that represents the class's start and stop time each day. When a user creates an assignment I want to check if the current time is between the two times of any of the classes. If it is I know that the assignment was created during that class. Here is my current code that does not work because .getTime() returns a date that includes month, and day, while I would just like to compare hours, and minutes. SO how can I trim the returned dates to just include the time in day? Would this be easier with joda-time, and if so what classes should be used?
public void checkTimeFrame() {
time = Calendar.getInstance().getTime();
ArrayList<SchoolClass> mList = mClassList;
// Changes index if assignment falls under time frame of class
for (int a = 0; a < mList.size(); a++) {
if (mList.get(a).getStartTime() != null && mList.get(a).getEndTime() != null &&
time.after(mList.get(a).getStartTime().getTime()) && time.before(mList.get(a)
.getEndTime().getTime())) {
index = a;
updateClassEditText();
}
}
}
JDK 8 Date-Time APIs are a good approach to solving these kinds of issues. Instead of Calendar , use LocalTime to store the start and end time of the class.
LocalTime now = LocalTime.now(ZoneId.systemDefault());
LocalTime start = mList.get(a).getStartTime();
LocalTime end = mList.get(a).getEndTime();
if(now.isAfter(start) && now.isBefore(end)){
//do something
}
For Android, you can use The ThreeTenABP project which adapts the java.time APIs for Android.
You can use Calendar.get(), as mentioned in another answer. To compare minutes, though, you should use Calendar.MINUTE, too:
int minutes_in_day = time.get(Calendar.HOUR_OF_DAY)*60 + time.get(Calendar.MINUTE);
Then, you can just compare the minutes within the day of the current time with that of the start and end times. This will, of course, only work when the times are in the same day.
The Calendar class has a get method where you can get different fields
e.g.
int hr = time.get(Calendar.HOUR_OF_DAY)
I will here only provide the Joda-Time-related answer you asked for. Joda-Time has the advantage to offer a dedicated type for the clock time, namely LocalTime. The old java.util.Calendar-stuff does not offer this advantage hence your difficulties.
First you convert an instance of java.util.Date like follows:
Date time = ...;
DateTime dt = new DateTime(time, DateTimeZone.getDefault());
LocalTime lt = dt.toLocalTime();
Note that the conversion is always timezone dependent. Then you can compare two LocalTime instances using the inherited methods isAfter(...) or isBefore(...).
try {
Date date1 = sdf.parse(given time);
Date date2 = sdf.parse("08:00 AM");
Date date3 = sdf.parse("06:00 PM");
if((date1.after(date2))&&(date1.before(date3))||date1.equals(date2) ||date1.equals(date3) ) {
}
} catch (ParseException e){
e.printStackTrace();
}
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).
This question already has answers here:
How can I determine if a date is between two dates in Java? [duplicate]
(11 answers)
Closed 9 years ago.
I'm trying to write a schedule program in Java and I need to figure out what time it is, and whether the current time is in between two set times. Figuring out the current time is pretty simple, but do you have any suggestions for figuring out whether it is between two times of day. For example, it is 9:33 AM on a Thursday. So I would need to figure out which scheduled section of the week that time corresponds to. How would I go about comparing the time to set periods during the week, for example an Array of sectioned times during a week such as {Monday from 9-10 AM, Tuesday from 3-4 PM, Thursday from 8-11 AM}, and seeing which section of time the current time falls between?
An efficient way to find which period any date lies within would be to have a class;
public class TimePeriod implements Comparable<TimePeriod>{
Date start;
Date end;
//Constructor, getters, setters
boolean isIn(Date date) {
return date.after(start) && date.before(end);
}
public int compareTo(TimePeriod other) {
return start.compareTo(other.start);
}
}
..and then create a sorted list of TimePeriod where you can perform a binary search.
edit:
This might make the binary search easier;
int check(Date date) {
if (isIn(date)) {
return 0;
} else if (start.after(date)) {
return -1;
} else if (end.before(date)) {
return 1;
} else {
throw new IllegalStateException("Time has gone badly wrong");
}
}
If you're using Date Class, you could do it like this
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm");
Date before = sdf.parse("07/05/2012 08:00");
Date after = sdf.parse("07/05/2012 08:30");
Date toCheck = sdf.parse("07/05/2012 08:15");
//is toCheck between the two?
boolean isAvailable = (before.getTime() < toCheck.getTime()) && after.getTime() > toCheck.getTime();
EDITED
As suggested by Jonathan Drapeau you could also use compareTo.
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm");
Date before = sdf.parse("07/05/2012 08:00");
Date after = sdf.parse("07/05/2012 08:30");
Date toCheck = sdf.parse("07/05/2012 08:15");
//is toCheck between the two?
if you want to include the "initial" and "final" date range
boolean isAvailable = before.compareTo(toCheck) >= 0 && after.compareTo(toCheck) <= 0
if you want to exclude the "initial" and "final" date range
boolean isAvailable = before.compareTo(toCheck) > 0 && after.compareTo(toCheck) < 0
You could use it too on Calendar class.
Anyway, i highly recommend you to use Calendar. It's a way precise class
you could check it like this:
Calendar cal1 = Calendar.getInstance(); // for example 12:00:00
Calendar cal2 = Calendar.getInstance(); // for exmaple 12:30:00
Calendar userTime = Calendar.getInstance(); // time to test: 12:15:00
if(user.after(cal1)&& user.before(cal2)){
//...
}
And to initialize and set times to Calendar, check this:
http://www.tutorialspoint.com/java/util/calendar_settime.htm
I would suggest using the Epoch time.
For a definition of Epoch time: http://en.wikipedia.org/wiki/Epoch_time
Basically, its a number of seconds after a specific date, i believe in 1989. If you translate the 3 times (the current time and the 2 times to compare to) in epoch time you can just use > < = etc.
For information on getting epoch time, Try here (has many languages): http://shafiqissani.wordpress.com/2010/09/30/how-to-get-the-current-epoch-time-unix-timestamp/
Unfortunately, my java is lacking or I'd give you some code :)
Edit:
Java epoch time code:
long epoch = System.currentTimeMillis()/1000;
Because my Java is bad and I don't have an interpreter where I am, I can only suggest using this site to help convert the other dates to epoch time: http://www.epochconverter.com/
There is before(Date) and after(Date) method in Date Class.
secondDate.before(firstDate)
If you use Calendar class, it has explicit before() and after() methods:
Calendar startDate = ...
Calendar endData = ...
isBetween = currentDate.after(startDate) && currentDate.before(endDate);
Please help me to write a method that returns number (int) of days from a provided day to the todays date.
So let's say, I am providing into a method an int 110515 (for May 15, 2011). It should return 9 (inclusive or exclusive is not important to me).
If you can use Joda, this is super simple:
Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();
Of course you could combine these.
int days = Days.daysBetween(startDate, endDate).getDays();
Joda objects can go back and forth between the JDK's date class pretty easily.
For the first part, make a DateFormatter then parse the string based on it, like this:
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyyMMdd");
DateTime dt = fmt.parseDateTime(strInputDateTime);
(After turning the int into a string of course.)
Should dates in the future include the current day? Meaning if today is May 24th 2011, should 110529 result in 4 or 5?
public static long numberOfDays(final long date) throws ParseException {
final Calendar compare = Calendar.getInstance();
compare.setTime(new SimpleDateFormat("yyMMdd").parse(String.valueOf(date)));
final int dstOffset = compare.get(Calendar.DST_OFFSET);
final long currentTimeMillis = System.currentTimeMillis();
final long compareTimeInMillis = compare.getTimeInMillis();
long difference = 0;
if (currentTimeMillis >= compareTimeInMillis) {
difference = currentTimeMillis - compareTimeInMillis - dstOffset;
} else {
difference = compareTimeInMillis - currentTimeMillis + dstOffset;
}
return difference / (24 * 60 * 60 * 1000);
}
Since this seems like a homework question I will help you out. You will want to use Calendar.getTimeInMillis. Then you will want to create a constant that is NUMBER_OF_MILLIS_IN_DAY . From there you subtract the initialDate from the currentDate (both time in millis) and divide by the constant.