Joda Time: How to get dates of weekdays on some date interval? - java

I have two LocalDates that represent some time interval. Now i have to get LocalDates of all fridays, that this interval contains.
Easiest way to do it?

package org.life.java.so.questions;
import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
/**
*
* #author Jigar
*/
public class JodaTimeDateTraverseQuestion {
public static void main(String[] args) {
DateTime startDt = new DateTime(2010,12,1,0,0,0,0);//1st Dec 2010
DateTime endDt = new DateTime(2010,12,31,0,0,0,0);//31st Dec 2010
DateTime tempDate = new DateTime(startDt.getMillis());
while(tempDate.compareTo(endDt) <=0 ){
if(tempDate.getDayOfWeek() != DateTimeConstants.SATURDAY && tempDate.getDayOfWeek() != DateTimeConstants.SUNDAY){
System.out.println(""+tempDate);
}
tempDate = tempDate.plusDays(1);
}
}
}

Solution: lazily step by one week.
import org.joda.time.LocalDate;
import java.util.Iterator;
public class DayOfWeekIterator implements Iterator<LocalDate>{
private final LocalDate end;
private LocalDate nextDate;
public DayOfWeekIterator(LocalDate start, LocalDate end, int dayOfWeekToIterate){
this.end = end;
nextDate = start.withDayOfWeek(dayOfWeekToIterate);
if (start.getDayOfWeek() > dayOfWeekToIterate) {
nextDate = nextDate.plusWeeks(1);
}
}
public boolean hasNext() {
return !nextDate.isAfter(end);
}
public LocalDate next() {
LocalDate result = nextDate;
nextDate = nextDate.plusWeeks(1);
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
Test
import org.joda.time.DateTimeConstants;
import org.joda.time.LocalDate;
public class DayOfWeekIteratorTest {
public static void main(String[] args) {
LocalDate startDate = new LocalDate(2010, 12, 1);//1st Dec 2010
LocalDate endDate = new LocalDate(2010, 12, 31);//31st Dec 2010
DayOfWeekIterator it = new DayOfWeekIterator(startDate, endDate, DateTimeConstants.FRIDAY);
while (it.hasNext()) {
System.out.println(it.next());
}
}
}

tl;dr
java.time.LocalDate.of( 2018 , Month.JANUARY , 23 ) // A date-only class in the modern *java.time* classes that supplant both Joda-Time and the troublesome old date-time classes.
.with(
TemporalAdjusters.next( DayOfWeek.FRIDAY ) // Nifty `TemporalAdjuster` implementation for moving to another date. Immutable Objects pattern means a new object is returned based on the original which remains unmodified.
)
.isBefore( // Compare `LocalDate` objects with `isBefore`, `isAfter`, and `isEqual`.
LocalDate.of( 2018 , Month.FEBRUARY , 27 );
)
java.time
FYI, the Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes.
Define your stop & start LocalDate objects.
LocalDate start = LocalDate.of( 2018 , Month.JANUARY , 23 );
LocalDate stop = LocalDate.of( 2018 , Month.FEBRUARY , 27 );
// TODO: Verify start.isBefore( stop ).
Collect the Friday dates we find. You might optimize a bit by sizing the collection.
// Pre-size the collection.
int initialCapacity = ( int ) ( ChronoUnit.WEEKS.between( start , stop ) + 2 ); // Adding two for good measure.
List < LocalDate > fridays = new ArrayList <>( initialCapacity );
Determine the first Friday, using the start date if it is itself a Friday. Use a pair of TemporalAdjuster implementations offered in the TemporalAdjusters class: next​(DayOfWeek) & nextOrSame​(DayOfWeek). Pass the desired day-of-week via the DayOfWeek enum, seven pre-defined objects, one for each day of the week Monday-Sunday.
LocalDate friday = start.with( TemporalAdjusters.nextOrSame( DayOfWeek.FRIDAY ) );
while ( friday.isBefore( stop ) )
{
fridays.add( friday ); // Remember this Friday date.
// Setup next loop.
friday = friday.with( TemporalAdjusters.next( DayOfWeek.FRIDAY ) );
}
System.out.println( "From " + start + " to " + stop + " = " + fridays );
From 2018-01-23 to 2018-02-27 = [2018-01-26, 2018-02-02, 2018-02-09, 2018-02-16, 2018-02-23]
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Related

How to compare current date with dates from API to display different ImageView if the date from API greater, less, or equal to current date in Kotlin [duplicate]

This question already has answers here:
How do I check if a date is within a certain range?
(17 answers)
Closed 5 years ago.
How do I compare dates in between in Java?
Example:
date1 is 22-02-2010
date2 is 07-04-2010 today
date3 is 25-12-2010
date3 is always greater than date1 and date2 is always today. How do I verify if today's date is in between date1 and date 3?
Date has before and after methods and can be compared to each other as follows:
if(todayDate.after(historyDate) && todayDate.before(futureDate)) {
// In between
}
For an inclusive comparison:
if(!historyDate.after(todayDate) && !futureDate.before(todayDate)) {
/* historyDate <= todayDate <= futureDate */
}
You could also give Joda-Time a go, but note that:
Joda-Time is the de facto standard date and time library for Java prior to Java SE 8. Users are now asked to migrate to java.time (JSR-310).
Back-ports are available for Java 6 and 7 as well as Android.
Use compareTo:
date1.compareTo(date2);
Following are most common way of comparing dates (my preference is Approach 1):
Approach 1: Using Date.before(), Date.after() and Date.equals()
if (date1.after(date2)) {
System.out.println("Date1 is after Date2");
}
if (date1.before(date2)) {
System.out.println("Date1 is before Date2");
}
if (date1.equals(date2)) {
System.out.println("Date1 is equal Date2");
}
Approach 2: Date.compareTo()
if (date1.compareTo(date2) > 0) {
System.out.println("Date1 is after Date2");
} else if (date1.compareTo(date2) < 0) {
System.out.println("Date1 is before Date2");
} else {
System.out.println("Date1 is equal to Date2");
}
Approach 3: Calender.before(), Calender.after() and Calender.equals()
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal1.setTime(date1);
cal2.setTime(date2);
if (cal1.after(cal2)) {
System.out.println("Date1 is after Date2");
}
if (cal1.before(cal2)) {
System.out.println("Date1 is before Date2");
}
if (cal1.equals(cal2)) {
System.out.println("Date1 is equal Date2");
}
tl;dr
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) ) ;
Boolean isBetween =
( ! today.isBefore( localDate1 ) ) // “not-before” is short for “is-equal-to or later-than”.
&&
today.isBefore( localDate3 ) ;
Or, better, if you add the ThreeTen-Extra library to your project.
LocalDateRange.of(
LocalDate.of( … ) ,
LocalDate.of( … )
).contains(
LocalDate.now()
)
Half-open approach, where beginning is inclusive while ending is exclusive.
Bad Choice of Format
By the way, that is a bad choice of format for a text representation of a date or date-time value. Whenever possible, stick with the standard ISO 8601 formats. ISO 8601 formats are unambiguous, understandable across human cultures, and are easy to parse by machine.
For a date-only value, the standard format is YYYY-MM-DD. Note how this format has the benefit of being chronological when sorted alphabetically.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
DateTimeFormatter
As your input strings are non-standard format, we must define a formatting pattern to match.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MM-uuuu" );
Use that to parse the input strings.
LocalDate start = LocalDate.parse( "22-02-2010" , f );
LocalDate stop = LocalDate.parse( "25-12-2010" , f );
In date-time work, usually best to define a span of time by the Half-Open approach where the beginning is inclusive while the ending is exclusive. So we want to know if today is the same or later than the start and also before the stop. A briefer way of saying “is the same or later than the start” is “not before the start”.
Boolean intervalContainsToday = ( ! today.isBefore( start ) ) && today.isBefore( stop ) ;
See the Answer by gstackoverflow showing the list of comparison methods you can call.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 brought some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android (26+) bundle implementations of the java.time classes.
For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
UPDATE: This “Joda-Time” section below is left intact as history. The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
Joda-Time
Other answers are correct with regard to the bundled java.util.Date and java.util.Calendar classes. But those classes are notoriously troublesome. So here's some example code using the Joda-Time 2.3 library.
If you truly want a date without any time portion and no time zone, then use the LocalDate class in Joda-Time. That class provides methods of comparison including compareTo (used with Java Comparators), isBefore, isAfter, and isEqual.
Inputs…
String string1 = "22-02-2010";
String string2 = "07-04-2010";
String string3 = "25-12-2010";
Define a formatter describing the input strings…
DateTimeFormatter formatter = DateTimeFormat.forPattern( "dd-MM-yyyy" );
Use formatter to parse the strings into LocalDate objects…
LocalDate localDate1 = formatter.parseLocalDate( string1 );
LocalDate localDate2 = formatter.parseLocalDate( string2 );
LocalDate localDate3 = formatter.parseLocalDate( string3 );
boolean is1After2 = localDate1.isAfter( localDate2 );
boolean is2Before3 = localDate2.isBefore( localDate3 );
Dump to console…
System.out.println( "Dates: " + localDate1 + " " + localDate2 + " " + localDate3 );
System.out.println( "is1After2 " + is1After2 );
System.out.println( "is2Before3 " + is2Before3 );
When run…
Dates: 2010-02-22 2010-04-07 2010-12-25
is1After2 false
is2Before3 true
So see if the second is between the other two (exclusively, meaning not equal to either endpoint)…
boolean is2Between1And3 = ( ( localDate2.isAfter( localDate1 ) ) && ( localDate2.isBefore( localDate3 ) ) );
Working With Spans Of Time
If you are working with spans of time, I suggest exploring in Joda-Time the classes: Duration, Interval, and Period. Methods such as overlap and contains make comparisons easy.
For text representations, look at the ISO 8601 standard’s:
durationFormat: PnYnMnDTnHnMnSExample: P3Y6M4DT12H30M5S(Means “three years, six months, four days, twelve hours, thirty minutes, and five seconds”)
intervalFormat: start/endExample: 2007-03-01T13:00:00Z/2008-05-11T15:30:00Z
Joda-Time classes can work with strings in both those formats, both as input (parsing) and output (generating strings).
Joda-Time performs comparisons using the Half-Open approach where the beginning of the span is inclusive while the ending is exclusive. This approach is a wise one for handling spans of time. Search StackOverflow for more info.
Compare the two dates:
Date today = new Date();
Date myDate = new Date(today.getYear(),today.getMonth()-1,today.getDay());
System.out.println("My Date is"+myDate);
System.out.println("Today Date is"+today);
if (today.compareTo(myDate)<0)
System.out.println("Today Date is Lesser than my Date");
else if (today.compareTo(myDate)>0)
System.out.println("Today Date is Greater than my date");
else
System.out.println("Both Dates are equal");
Update for Java 8 and later
isAfter()
isBefore()
isEqual()
compareTo()
These methods exists in LocalDate, LocalTime, and LocalDateTime classes.
Those classes are built into Java 8 and later. Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).
You can use Date.getTime() which:
Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
represented by this Date object.
This means you can compare them just like numbers:
if (date1.getTime() <= date.getTime() && date.getTime() <= date2.getTime()) {
/*
* date is between date1 and date2 (both inclusive)
*/
}
/*
* when date1 = 2015-01-01 and date2 = 2015-01-10 then
* returns true for:
* 2015-01-01
* 2015-01-01 00:00:01
* 2015-01-02
* 2015-01-10
* returns false for:
* 2014-12-31 23:59:59
* 2015-01-10 00:00:01
*
* if one or both dates are exclusive then change <= to <
*/
Try this
public static boolean compareDates(String psDate1, String psDate2) throws ParseException{
SimpleDateFormat dateFormat = new SimpleDateFormat ("dd/MM/yyyy");
Date date1 = dateFormat.parse(psDate1);
Date date2 = dateFormat.parse(psDate2);
if(date2.after(date1)) {
return true;
} else {
return false;
}
}
Use getTime() to get the numeric value of the date, and then compare using the returned values.
This code determine today is in some duration.. based on KOREA locale
Calendar cstart = Calendar.getInstance(Locale.KOREA);
cstart.clear();
cstart.set(startyear, startmonth, startday);
Calendar cend = Calendar.getInstance(Locale.KOREA);
cend.clear();
cend.set(endyear, endmonth, endday);
Calendar c = Calendar.getInstance(Locale.KOREA);
if(c.after(cstart) && c.before(cend)) {
// today is in startyear/startmonth/startday ~ endyear/endmonth/endday
}
This method worked for me:
public static String daysBetween(String day1, String day2) {
String daysBetween = "";
SimpleDateFormat myFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date date1 = myFormat.parse(day1);
Date date2 = myFormat.parse(day2);
long diff = date2.getTime() - date1.getTime();
daysBetween = ""+(TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS));
} catch (ParseException e) {
e.printStackTrace();
}
return daysBetween;
}

Split a time period into hourly intervals

How do I divide a time period (10:00:00PM - 20:30:00PM) into hourly intervals using java to get the following result?
10:00:00 - 11:00:00
11:00:00 - 12:00:00
12:00:00 - 13:00:00
13:00:00 - 14:00:00
15:00:00 - 16:00:00
16:00:00 - 17:00:00
17:00:00 - 18:00:00
19:00:00 - 20:00:00
20:00:00 - 20:30:00
Make a LocalTime of the start and stop.
Add an hour to the start.
LocalTime lt = start.plusHours( 1 ) ;
Notice the immutable objects. Rather than alter the original object, we get a fresh new LocalTime object.
Compare to the stop by calling the isBefore, isAfter, and isEqual methods. If not yet past the stop, add another hour. If going past the stop, then use the stop itself rather than the next hour.
Collect into a List < LocalTime>.
If you want to track each entry as pair of LocalTime objects, define a class named something like TimeSlot with a pair of LocalTime member fields. The new Records feature previewed in Java 14 would do nicely here.
All this has been covered many times already on Stack Overflow. Search to learn more.
Example app
Here is a working example app. This uses the new Records feature defined in JEP 359: Records (Preview), previewed in Java 14, working in IntelliJ 2020.1 IDE.
package work.basil.example;
import java.time.Duration;
import java.time.LocalTime;
public record LocalTimeRange(LocalTime start , LocalTime stop)
{
}
We can fancy that up a bit.
We override toString to produce text in one of the four standard ISO 8601 format: HH:MM/HH:MM. We define an enum for the four types of formats specified by ISO 8601 for time intervals. Our format method takes one of those flags to produce text in one of the four standard formats.
We produce a Duration object if asked. This class represents a span-of-time not attached to the timeline on a scale of hours-minutes-seconds.
Because this is a record, we need not override equals & hashCode. Nor do we need getter methods for the parts of start and end LocalTime objects.
package work.basil.example;
import java.time.Duration;
import java.time.LocalTime;
public record LocalTimeRange(LocalTime start , LocalTime end)
{
public enum Format
{ START_AND_END, START_AND_DURATION, DURATION_AND_END, DURATION_ONLY } // Per ISO 8601 standard.
#Override
public String toString ( ) { return this.format( Format.START_AND_END ); } // Per ISO 8601 standard.
public Duration toDuration ( ) { return Duration.between( this.start , this.end ); }
public String format ( LocalTimeRange.Format format )
{
return switch ( format )
{
case START_AND_END -> this.start + "/" + this.end;
case START_AND_DURATION -> this.start.toString() + "/" + this.toDuration().toString();
case DURATION_AND_END -> this.toDuration().toString() + "/" + this.end.toString();
case DURATION_ONLY -> this.toDuration().toString();
};
}
}
We need a method to create the hourly time ranges.
private List < LocalTimeRange > hourlyRanges ( final LocalTime start , final LocalTime stop )
{
// Verify arguments
Objects.requireNonNull( start , "Received null time-of-day for start. Message # 51521a5c-5f49-4c74-98e3-fce2587edf77." );
Objects.requireNonNull( stop , "Received null time-of-day for stop. Message # 41b98429-4edb-4209-a12f-e266dcae4a90." );
// Logic
int initialCapacity = java.lang.Math.toIntExact( Duration.between( start , stop ).toHours() + 1 ); // Returns the value of the long argument; throwing an exception if the value overflows an int.
ArrayList < LocalTimeRange > ranges = new ArrayList <>( initialCapacity );
LocalTime localTime = start;
while ( ! localTime.isAfter( stop ) )
{
LocalTimeRange range = null;
LocalTime hourLater = localTime.plusHours( 1 );
if ( ! hourLater.isAfter( stop ) )
{
range = new LocalTimeRange( localTime , hourLater );
} else
{
range = new LocalTimeRange( localTime , stop );
}
Objects.requireNonNull( range );
ranges.add( range );
// Prepare for next loop.
localTime = hourLater;
}
ranges.trimToSize();
return Objects.requireNonNull( ranges );
}
And some code to exercise it.
LocalTime start = LocalTime.parse( "10:00:00" );
LocalTime end = LocalTime.parse( "20:30:00" );
List < LocalTimeRange > ranges = this.hourlyRanges( start , end );
System.out.println( "ranges = " + ranges );
System.out.println( ranges.stream().map( range -> range.toDuration() ).collect( Collectors.toList() ) );
System.out.println( ranges.stream().map( range -> range.format( LocalTimeRange.Format.START_AND_END ) ).collect( Collectors.toList() ) );
System.out.println( ranges.stream().map( range -> range.format( LocalTimeRange.Format.START_AND_DURATION ) ).collect( Collectors.toList() ) );
System.out.println( ranges.stream().map( range -> range.format( LocalTimeRange.Format.DURATION_AND_END ) ).collect( Collectors.toList() ) );
System.out.println( ranges.stream().map( range -> range.format( LocalTimeRange.Format.DURATION_ONLY ) ).collect( Collectors.toList() ) );
When run:
ranges = [10:00/11:00, 11:00/12:00, 12:00/13:00, 13:00/14:00, 14:00/15:00, 15:00/16:00, 16:00/17:00, 17:00/18:00, 18:00/19:00, 19:00/20:00, 20:00/20:30]
[PT1H, PT1H, PT1H, PT1H, PT1H, PT1H, PT1H, PT1H, PT1H, PT1H, PT30M]
[10:00/11:00, 11:00/12:00, 12:00/13:00, 13:00/14:00, 14:00/15:00, 15:00/16:00, 16:00/17:00, 17:00/18:00, 18:00/19:00, 19:00/20:00, 20:00/20:30]
[10:00/PT1H, 11:00/PT1H, 12:00/PT1H, 13:00/PT1H, 14:00/PT1H, 15:00/PT1H, 16:00/PT1H, 17:00/PT1H, 18:00/PT1H, 19:00/PT1H, 20:00/PT30M]
[PT1H/11:00, PT1H/12:00, PT1H/13:00, PT1H/14:00, PT1H/15:00, PT1H/16:00, PT1H/17:00, PT1H/18:00, PT1H/19:00, PT1H/20:00, PT30M/20:30]
[PT1H, PT1H, PT1H, PT1H, PT1H, PT1H, PT1H, PT1H, PT1H, PT1H, PT30M]
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
This solved part of my problem:
private ArrayList<String> setInterval(String start, String stop) throws ParseException {
String strStart;
String strEnd;
ArrayList<String> arrayList = new ArrayList<>();
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
Date dStart = df.parse(start);
Date dStop = df.parse(stop);
Calendar cal = Calendar.getInstance();
cal.setTime(dStart);
cal.add(Calendar.HOUR, 1); //minus number would decrement the days
while (cal.getTime().before(dStop)) {
strStart = df.format(cal.getTime());
cal.add(Calendar.HOUR, 1);
strEnd = df.format(cal.getTime());
arrayList.add(strStart + " - " + strEnd);
}
return arrayList;
}

JodaTime - Number of days in each months between 2 dates

I have 2 dates like this :
DateTime startingDate = new DateTime(STARTING_YEAR, STARTING_MONTH, STARTING_DAY, 0, 0);
DateTime endingDate = new DateTime(ENDING_YEAR, ENDING_MONTH, ENDING_DAY, 0, 0);
TOTAL_DAYS = Days.daysBetween(startingDate, endingDate).getDays();
It is easy to know the total days between, but I'm not familiar at all with the API and would like to know if there is an easier way to find the number of days in each months between 2 dates without loops and ifs.
Example :
DateTime startingDate = new DateTime(2000, 1, 1, 0, 0);
DateTime endingDate = new DateTime(2000, 2, 3, 0, 0);
Would give 31 for January and 2 for February.
Thanks!
I did it with a loop finally.
DateTime startingDate = new DateTime(STARTING_YEAR, STARTING_MONTH, STARTING_DAY, 0, 0);
DateTime endingDate = new DateTime(ENDING_YEAR, ENDING_MONTH, ENDING_DAY, 0, 0);
TOTAL_DAYS = Days.daysBetween(startingDate, endingDate).getDays();
DateTime currentDate = startingDate;
System.out.println(currentDate.dayOfMonth().getMaximumValue() - currentDate.dayOfMonth().get() + 1);
currentDate = currentDate.plus(Period.months(1));
while (currentDate.isBefore(endingDate)) {
System.out.println(currentDate.dayOfMonth().getMaximumValue());
currentDate = currentDate.plus(Period.months(1));
}
System.out.println(endingDate.dayOfMonth().get());
double days = (endingDate.getMillis()-startingDate.getMillis())/86400000.0;
that gives the number of days as a floating point number. truncate if you only want the number of full days.
This may help:
DateTime startingDate = new DateTime(2000, 1, 1, 0, 0);
DateTime endingDate = new DateTime(2000, 2, 3, 0, 0);
Duration duration = new Duration(startingDate, endingDate);
System.out.println(duration.getStandardDays());//get the difference in number of days
FYI, the Joda-Time project, now in maintenance mode, advises migration to java.time.
java.time
You will need to iterate if you want to address each intervening month individually. But this job is somewhat simplified by the YearMonth class. Furthermore, you can mask away the iteration by using Streams.
Half-Open
The java.time classes wisely use the Half-Open approach to defining a span of time. This means the beginning is inclusive while the ending is exclusive. So a range of months needs to end with the month following the ending target month.
TemporalAdjuster
The TemporalAdjuster interface provides for manipulation of date-time values. The TemporalAdjusters class (note the plural s) provides several handy implementations. Here we need:
TemporalAdjusters.firstDayOfNextMonth()
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
LocalDate startDate = LocalDate.of( 2000 , 1 , 1 );
YearMonth ymStart = YearMonth.from( startDate );
LocalDate stopDate = LocalDate.of( 2000 , 2 , 3 );
LocalDate stopDateNextMonth = stopDate.with( TemporalAdjusters.firstDayOfNextMonth() );
YearMonth ymStop = YearMonth.from( stopDateNextMonth );
Loop each month in between.
You can ask for a localized name of the month, by the way, via the Month enum object.
YearMonth ym = ymStart;
do {
int daysInMonth = ym.lengthOfMonth ();
String monthName = ym.getMonth ().getDisplayName ( TextStyle.FULL , Locale.CANADA_FRENCH );
System.out.println ( ym + " : " + daysInMonth + " jours en " + monthName );
// Prepare for next loop.
ym = ym.plusMonths ( 1 );
} while ( ym.isBefore ( ymStop ) );
2000-01 : 31 jours en janvier
2000-02 : 29 jours en février
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Creating a DateTime from two other dates

Basically I want to see if someones birthday is within 3 months of todays date. I am going to use Days to do this and just say "90" days.
My thoughts are as follows:
I will set a new datetime as todays date and then grab the DOB of the person in question.
I will then want to take the day and month from the DOB and the year from Todays date.
Then these days, months and years will be merged into one new date.
For example:
DOB 04/05/1987
Today 10/05/2013
NewBirth 04/05/2013
How can I achieve the part where I grab the days/months from one date, years from another, and put these into one date?
(Only key factors, im aware this rule wouldn't run)
import org.joda.time.ReadableInstant;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.Months;
import org.joda.time.Years;
rule"Blah"
salience 1
when
Proposer($dob : dateOfBirth)
then
DateTime NewBirth = new DateTime()
DateTime today = new DateTime();
#grab DOB day and month
#grab Todays year
#turn "NewBirth" into a combination of the above 2 lines
int $birthday = (Days.daysBetween((ReadableInstant)today,(ReadableInstant)NewBirth).getDays());
If ($birthday <= 90){
logger.info("HURRRAAAYYYYYY");
}
end
I would do it with the standard JDK Calendar
boolean isWithin3Month(int y, int m, int d) {
Calendar now = Calendar.getInstance();
Calendar birthday = new GregorianCalendar(y, m, d);
int currentMonth = now.get(Calendar.MONTH);
int birthDayMonth = birthday.get(Calendar.MONTH);
int monthDiff;
if (birthDayMonth < currentMonth) { // eg birth = Jan (0) and curr = Dec (11)
monthDiff = 12 - currentMonth + birthDayMonth;
} else {
monthDiff = birthDayMonth - currentMonth;
}
if (monthDiff < 0 || monthDiff > 3) {
return false;
} else if (monthDiff == 0) {
return birthday.get(Calendar.DATE) >= now.get(Calendar.DATE);
}
return true;
}
java.time
The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
You apparently want to know if the birthday anniversary lands between today and 90 days from today. So determine that 90 day limit.
LocalDate ninetyDaysFromToday = today.plusDays( 90 );
Get the birthdate.
LocalDate birthdate = LocalDate.of( 1987 , Month.APRIL , 5 ) ;
MonthDay
The MonthDay class represents, well, a month and a day-of-month, without any year. You can adjust into a year to get a date. Perfect for adjusting that birthday into this year.
If the birthday of this year is already past, then we need to consider next year’s birthday, as the 90 day limit may wrap over into the new year.
MonthDay mdBirthday = MonthDay.from( birthdate );
MonthDay mdToday = MonthDay.from( today );
int y = mdBirthday.isBefore( mdToday ) ? ( today.getYear()+1 ) : today.getYear() ;
LocalDate nextBirthday = mdBirthday.atYear( y );
Boolean nextBirthdayIsWithinNextNinetyDays = nextBirthday.isBefore( ninetyDaysFromToday );
Or another way to do the same.
LocalDate nextBirthday = MonthDay.from( birthdate ).atYear( today.getYear() ) ; // Possibly the next birthday, not yet sure.
if( nextBirthday.isBefore( today ) ) {
// This year’s birthday is past, so increment the year to get next birthday.
nextBirthday = nextBirthday.plusYears( 1 );
}
Boolean nextBirthdayIsWithinNextNinetyDays = nextBirthday.isBefore( ninetyDaysFromToday );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Try
DateTime newBirth = new DateTime(today.year(), $dob.monthOfYear(), $dob.dayOfMonth(), 00, 00);
instead of the parameterless constructer at the beginning of your then statement.
Ended up managing to do it with Jodatime,
rule"Less than 3months before Birthday Discount"
when
Proposer($dob : dateOfBirth)
then
DateTime today = new DateTime();
DateTime newBirth = new DateTime(today.year().get()+"-"+$dob.monthOfYear().get()+"-"+$dob.dayOfMonth().get());
int $birthday = (Days.daysBetween((ReadableInstant)today,(ReadableInstant)newBirth).getDays());
if($birthday <=90 && $birthday>0){
logger.info("discount applied");
}
end

Joda time - all mondays between two dates

I am using Joda time api in a Spring 3.0 project for the very first time. Now I have a start and end date and I want to get the date for all mondays between these two dates. How can I do this ?
I have no idea where to start, can someone please advise. I looked at theis post Joda Time: How to get dates of weekdays on some date interval? and it offered some sort of guidance but its still somewhat vague due to little experience with joda.
LocalDate startDate = new LocalDate(2011, 11, 8);
LocalDate endDate = new LocalDate(2012, 5, 1);
LocalDate thisMonday = startDate.withDayOfWeek(DateTimeConstants.MONDAY);
if (startDate.isAfter(thisMonday)) {
startDate = thisMonday.plusWeeks(1); // start on next monday
} else {
startDate = thisMonday; // start on this monday
}
while (startDate.isBefore(endDate)) {
System.out.println(startDate);
startDate = startDate.plusWeeks(1);
}
I recently developed Lamma which is designed to solve this exact use case:
Dates.from(2011, 11, 8).to(2011, 12, 30).byWeek().on(DayOfWeek.MONDAY).build();
and you will get a List<Date> of:
Date(2011,11,14)
Date(2011,11,21)
Date(2011,11,28)
Date(2011,12,5)
Date(2011,12,12)
Date(2011,12,19)
Date(2011,12,26)
FYI, the Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes.
Using java.time
The LocalDate class is java.time is akin to the Joda-Time LocalDate. A date-only value, without time-of-day and without time zone. One difference is that java.time eschews constructors for factory methods.
LocalDate start = LocalDate.of( 2011 , 11 , 8 );
LocalDate stop = LocalDate.of( 2012 , 5 , 1 );
Collect the Mondays.
List<LocalDate> mondays = new ArrayList<>();
The TemporalAdjuster interface provides for classes that manipulate date-time values. The TemporalAdjusters class (note the plural name) provides various implementations. We want the nextOrSame and next adjusters, passing the desired DayOfWeek.MONDAY enum object.
LocalDate monday = start.with( TemporalAdjusters.nextOrSame( DayOfWeek.MONDAY ) );
while( monday.isBefore( stop ) ) {
mondays.add( monday );
// Set up the next loop.
monday = monday.plusWeeks( 1 );
}
By the way, usually the wise approach in handling a span of time is Half-Open where the beginning is inclusive while the ending is exclusive. So in the code above we are running up to, but not including, the stop date.
If the ending is inclusive, use the negation of isAfter e.g.
while( !monday.isAfter( stop ) ) {
//...
}
Here, monday is not after stop means it is before or up to stop.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 brought some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android (26+) bundle implementations of the java.time classes.
For earlier Android (<26), the process of API desugaring brings a subset of the java.time functionality not originally built into Android.
If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….
This code takes to string dates and gives the number of sundays and also all the sunday's dates
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class FindAllSundays {
public static int getNumberofSundays(String d1, String d2) throws Exception { // object
// in
// Date
// form
Date date1 = getDate(d1);
Date date2 = getDate(d2);
Calendar c1 = Calendar.getInstance();
c1.setTime(date1);
Calendar c2 = Calendar.getInstance();
c2.setTime(date2);
int sundays = 0;
while (c2.after(c1)) {
// System.out.println(" came here ");
//checks to see if the day1 ....so on next days are sundays if sunday goes inside to increment the counter
if (c1.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
System.out.println(c1.getTime().toString() + " is a sunday ");
sundays++;
}
c1.add(Calendar.DATE, 1);
}
System.out.println("number of sundays between 2 dates is " + sundays);
return sundays;
}
// converts string to date
public static Date getDate(String s) {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = format.parse(s);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return date;
}
public static void main(String[] arg) throws Exception {
System.out.println(" " + getNumberofSundays("2005-10-07", "2006-10-01"));
}
}
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
public class Get_time {
public ArrayList<LocalDate> getmondays(String s,String e)
{
LocalDate start = LocalDate.parse(s);
LocalDate end = LocalDate.parse(e);
List<LocalDate> totalDates_Mondays = new ArrayList<>();
while (!start.isAfter(end)) {
totalDates_Mondays.add(start);
start = start.plusWeeks(1);
}
return (ArrayList<LocalDate>) totalDates_Mondays;
}
public static void main(String ...s1) {
String mon_start = "1600-08-01";
String mon_end= "2016-12-29";
Get_time t=new Get_time();
System.out.println(t.getmondays(mon_start,mon_end));
}
}
In Java 8 using Stream ,
LocalDate startDate = LocalDate.of(2019, 2, 1);
LocalDate endDate = LocalDate.of(2019, 2, 28);
long numOfDays = ChronoUnit.DAYS.between(startDate, endDate);
List<LocalDate> daysRange = Stream.iterate(startDate, date -> date.plusDays(1)).limit(numOfDays).filter( date -> date.getDayOfWeek()==DayOfWeek.MONDAY ).collect(Collectors.toList());

Categories

Resources