I have never used Joda-Time before but I have ArrayList which contains objects with LocalDate and count. So I have count for each day in ArrayList and each day is only once in ArrayList.
I need to calculate counts for each month of year, which is in list.
My data:
E.g.:
dd.MM.yyyy
17.01.1996 (count 2)
18.01.1996 (count 3)
19.02.1996 (count 4)
19.03.1996 (count 1)
18.05.1997 (count 3)
Now I want outpur like this:
MM.yyyy
01.1996 -> 2 (17.1.1996) + 3 (18.1.1996) = 5
02.1996 -> 4 (19.2.1996) = 4
03.1996 -> 1 (19.3.1996) = 1
05.1997 -> 3 (18.5.1997) = 3
Simply I need to get count for each month, but I do not know what would be best way to achieve this.
Data class:
private class Info{
int count;
LocalDate day;
}
And result I would put in some class which contains Month and Year date + count.
In Joda-Time, there is class that represents Year + Month information, named YearMonth.
What you need to do is mostly construct a Map<YearMonth, int> to store the count of each YearMonth, by looping through your original List which contains LocalDate and count, and update the map accordingly.
Conversion from LocalDate to YearMonth should be straight forward: YearMonth yearMonth = new YearMonth(someLocalDate); should work
in pseudo-code, it looks like:
List<Info> dateCounts = ...;
Map<YearMonth, Integer> monthCounts = new TreeMap<>();
for (Info info : dateCounts) {
YearMonth yearMonth = new YearMonth(info.getLocalDate());
if (monthCounts does not contains yearMonth) {
monthCounts.put(yearMonth, info.count);
} else {
oldCount = monthCounts.get(yearMonth);
monthCounts.put(yearMonth, info.count + oldCount);
}
}
// feel free to output content of monthCounts now.
// And, with TreeMap, the content of monthCounts are sorted
You are looking for the getMonthOfYear and getYear methods on the LocalDate class in Joda-Time 2.3.
for ( Info info : infos ) {
int year = info.day.getYear();
int month = info.day.getMonthOfYear();
}
From there, write code to roll-up the count in any way that suits you. You could keep a map of years as keys leading to a map of months. You could create a string in the format of "YYYY-MM" as a key to map.
Related
For a schedule app I need to determine the first day after today from a list, going forwards. So for example:
DayOfWeek today -> SATURDAY
val list1 = listOf(MONDAY, TUESDAY, FRIDAY)
DayOfWeek today -> WEDNESDAY
val list2 = listOf(TUESDAY)
The logic would then have to give me MONDAY for list1 and TUESDAY for list2. I am aware of the .plusDays() function on the DayOfWeek enum class and the TemporalAdjusters.nextOrSame() but you then have to supply a DayOfWeek, which I don't know since I'm trying to find it inside the list.
LocalDate today = LocalDate.now(ZoneId.systemDefault());
List<DayOfWeek> list = List.of(DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.FRIDAY);
DayOfWeek first = Collections.min(list,
Comparator.comparing(dow -> today.with(TemporalAdjusters.nextOrSame(dow))));
System.out.println(first);
Output when running today (Saturday in my time zone):
MONDAY
I am querying the minimum using a comparator that compares the date of the next occurrence of that day of week (today if today happens to be that day). Since Monday comes first, this is regarded as the minimum. I am indirectly calling the TemporalAdjusters.nextOrSame() method that you mentioned on each member of your list. It may not be the most time efficient approach, but for 19 out of 20 purposes I’m sure it’s fine. And it gives code that is short and that I find readable, that’s more important.
If today is Wednesday? Let’s just try setting today to next Wednesday:
LocalDate today = LocalDate.of(2021, Month.JUNE, 23);
Now output is:
FRIDAY
Here's Ole V.V.'s answer, translated into Kotlin as a function.
fun nextWeekDayInList(list: List<DayOfWeek>, today: LocalDate) =
list.minByOrNull { dow ->
today.with(TemporalAdjusters.nextOrSame(dow))
}
This will return null if the list is empty.
Usage:
println(nextWeekDayInList(
listOf(DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.FRIDAY),
today = LocalDate.now(ZoneId.systemDefault())
))
Judging from your recent comment, next might be more suitable than nextOrSame.
I am late, but I have created a solution. So, posting it.
package com.ubaid;
import lombok.extern.slf4j.Slf4j;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;
#Slf4j
public class Demo {
public static void main(String[] args) {
List<DayOfWeek> list = List.of(DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.FRIDAY);
DayOfWeek nextDay = getFirstDayInListAfterTodayGoingForward(list);
//will print MONDAY (today is SATURDAY)
log.debug(String.valueOf(nextDay));
list = List.of(DayOfWeek.TUESDAY);
nextDay = getFirstDayInListAfterTodayGoingForward(list);
//will print TUESDAY (today is SATURDAY)
log.debug(String.valueOf(nextDay));
}
/**
*
* #param list of days of week
* #return first day of week after today or today if today is present in the list
*/
private static DayOfWeek getFirstDayInListAfterTodayGoingForward(List<DayOfWeek> list) {
//MONDAY value is 1
// .
// .
//SUNDAY value is 7
//getting today value
int todayVal = DayOfWeek.from(LocalDate.now()).getValue();
//sort the DAYS according to their ordinal values
List<Integer> daysInListVal = list
.stream()
.map(DayOfWeek::getValue)
.sorted()
.collect(Collectors.toList());
if (daysInListVal.contains(todayVal)) {
return DayOfWeek.of(todayVal);
}
//now get the DAY value which is next to today DAY
//If next value is not present then pick the first item of sorted list
return daysInListVal
.stream()
.filter(dayInList -> dayInList > todayVal)
.findFirst()
.map(DayOfWeek::of)
.orElse(DayOfWeek.of(daysInListVal.stream().findFirst().orElseThrow()));
}
}
I need to write a daymanagerr that assigns time slots for orders in a restaurant.
That's the daymanager:
public DayManager (LocalDate date, int numberOfTimeSlots, int capacityPerSlot) {
this.date = date;
this.capacityPerSlot = capacityPerSlot;
this.numberOfTimeSlots = numberOfTimeSlots;
For each day I can choose the number of available slots and the capacity per slot (so if I choose 3 slots and a capacity of 3 per slot, that's 9 slots in total).
Every customer can state their preferred time slot (here: 0, 1 or 2) with their order.
Here's my class for adding orders:
public Optional<Integer> addOrder(Order order, int preferredSlot) {
int givenSlot = 0, count = 1;
List<Integer> slots = new ArrayList<Integer>();
List<Integer> slotsPerSlot = new ArrayList<Integer>();
if ((slots.size() * slotsPerSlot.size()) <= (numberOfTimeSlots * capacityPerSlot)) {
if (slots.contains(preferredSlot) == false) {
givenSlot = preferredSlot;
slots.add(preferredSlot);
slotsPerSlot.add(count);
count++;
} else if (slotsPerSlot.size() <= capacityPerSlot) {
givenSlot = preferredSlot;
slots.add(preferredSlot);
slotsPerSlot.add(slotsPerSlot.size() + 1);
} else {
givenSlot = slots.get(slots.lastIndexOf(count));
}
return Optional.of(givenSlot);
}
return Optional.empty();
}
What I need help with:
With every new order I get, I need to check if there is still capacity left in that customers preferred slot. If there is capacity left, I assign that slot to him. If there is no capacity left in that slot, I assign the slot with the next lowest index (and available capacity). If there is no capacity left for that day, I simply return nothing.
I just can't figure out how to create a slotsPerSlot list for each slot and additionally I don't really know, how I could get the next lowest slot number.
Multimap
You could use a multimap. A Map is a pairing of key that leads to a value. In a multimap, the value is actually a collection of values rather than a single value.
Imagine, for example, a hierarchy of three time slots where the first and last contain an empty list (no orders yet), while the middle time slot has a list of a single order.
2022-01-23T13:00-07:00[America/Edmonton]
[]
2022-01-23T14:00-07:00[America/Edmonton]
[Order[id=2d8e5cc2-26ac-474d-a081-2c71207fd6c5, customerName=Basil]]
2022-01-23T15:00-07:00[America/Edmonton]
[]
(Minor detail: The 2d8e5cc2-26ac-474d-a081-2c71207fd6c5 text is a hexadecimal string representation of a 128-bit UUID value used to identify that particular order.)
Example code
Here is some example code. This code is incomplete, but will get you going in the right direction.
First, define our Order class. We will make it a record, using the new feature in Java 16. You could just as well define a conventional class, but a record is so much briefer. The compiler implicitly creates the constructor, getters, equals & hashCode, and toString.
package work.basil.example.orders;
import java.util.UUID;
public record Order(UUID id , String customerName)
{
}
Define the DayManager class.
The constructor is the place to set up your data structure for tracking orders. You were doing that work inside your addOrder method which makes no sense.
The goal of the constructor is to populate a NavigableMap, a Map that maintains its keys it a sorted order. We use TreeMap as the concrete implementation of the NavigableMap interface.
The keys to our map are ZonedDateTime, a date with time-of-day within the context of a time zone. Each ZonedDateTime object is the start of each time slot. I use this approach rather than your mere integer number to identify each slot.
The values of our map are a list of Order objects. As we add orders to our tracking system, they land in one of these lists. Each list is tied to a ZonedDateTime object as the time slot in our map. The problem with using a List is that the class is meant to be a resizable collection. So our code here manages the size limits, checking the current size to get a count of how many orders are already present in the list. We compare that count to our capacity-per-time-slot number we keep as a member field on DayManager class.
If we are under capacity, we add our order to the list, and return an Optional containing the ZonedDateTime to identify the time slot.
If we are at capacity, we need to move on to the next time slot — this I leave as an exercise for the reader.
Hint: We have a ZonedDateTime in hand, the current key used to access our map. So if we add the Duration stored as a member field, we will obtain the next key in our map. Use that key to get the next list of orders. Lather, rinse, repeat, until moving past the last time slot of the day.
By the way, in real work, I would look to a third-party library such as Eclipse Collections or Google Guava for a fixed-size list class. Better to rely on code that is already written and tested than rely on our size-checking code here.
We pre-populate our map with time slots and empty lists in the constructor. So we have a data structure in place when we begin adding orders.
The addOrder method looks for the requested time slot as the key in the map. Doing a get on the map returns a List of orders for us to inspect.
package work.basil.example.orders;
import java.time.*;
import java.util.*;
public class DayManager
{
// Member fields.
final ZoneId zoneId;
final LocalDate workDate;
final LocalTime startTime;
final Duration timeSlice;
final int numberOfTimeSlots, capacityPerTimeSlot;
private final NavigableMap < ZonedDateTime, List < Order > > ordersPerTimeSlot;
// Constructor
public DayManager ( final ZoneId zoneId , final LocalDate localDate , final LocalTime startTime , final Duration timeSlice , final int numberOfTimeSlots , final int capacityPerSlot )
{
this.zoneId = zoneId;
this.workDate = localDate;
this.startTime = startTime;
this.timeSlice = timeSlice;
this.numberOfTimeSlots = numberOfTimeSlots;
this.capacityPerTimeSlot = capacityPerSlot;
this.ordersPerTimeSlot = new TreeMap <>();
this.populateMap();
}
// Subroutine.
private void populateMap ( )
{
ZonedDateTime start = ZonedDateTime.of( this.workDate , this.startTime , this.zoneId );
for ( int i = 0 ; i < this.numberOfTimeSlots ; i++ )
{
Duration d = this.timeSlice.multipliedBy( i );
ZonedDateTime zdt = start.plus( d );
List < Order > list = new ArrayList <>( this.capacityPerTimeSlot );
this.ordersPerTimeSlot.put( zdt , list );
}
System.out.println( "this.ordersPerTimeSlot = " + this.ordersPerTimeSlot );
}
// Business logic.
public Optional < ZonedDateTime > addOrder ( final Order order , final ZonedDateTime zdt )
{
List < Order > orders = this.ordersPerTimeSlot.get( zdt );
if ( Objects.isNull( orders ) ) { return Optional.empty(); }
if ( orders.size() > this.capacityPerTimeSlot )
{
String msg = "ERROR - Capacity per time slot exceeded. ";
System.out.println( msg );
throw new IllegalStateException( msg );
} else if ( orders.size() == this.capacityPerTimeSlot )
{
String msg = "INFO - This time slot filled.";
System.out.println( msg );
throw new IllegalStateException( msg );
} else if ( orders.size() < this.capacityPerTimeSlot )
{
// Room in this time slot to place order.
orders.add( order );
return Optional.of( zdt );
} else
{
String msg = "ERROR - Should never reach this point. Error in IF-THEN logic of adding orders.";
System.out.println( msg );
throw new IllegalStateException( msg );
}
}
// Debugging
public String dumpOrders ( )
{
return this.ordersPerTimeSlot.toString();
}
}
Here is an App class for exercising our DayManager & Order classes.
package work.basil.example.orders;
import java.time.*;
import java.util.Optional;
import java.util.UUID;
public class App
{
public static void main ( String[] args )
{
ZoneId z = ZoneId.of( "America/Edmonton" );
LocalDate ld = LocalDate.of( 2022 , Month.JANUARY , 23 );
DayManager dm = new DayManager( z , ld , LocalTime.of( 13 , 0 ) , Duration.ofHours( 1 ) , 3 , 3 );
Order order = new Order( UUID.fromString( "2d8e5cc2-26ac-474d-a081-2c71207fd6c5" ) , "Basil" );
Optional < ZonedDateTime > optionalTimeSlot = dm.addOrder( order , ZonedDateTime.of( ld , LocalTime.of( 14 , 0 ) , z ) );
System.out.println( "order = " + order );
System.out.println( "optionalTimeSlot.toString() = " + optionalTimeSlot );
System.out.println( dm.dumpOrders() );
}
}
When run.
this.ordersPerTimeSlot = {2022-01-23T13:00-07:00[America/Edmonton]=[], 2022-01-23T14:00-07:00[America/Edmonton]=[], 2022-01-23T15:00-07:00[America/Edmonton]=[]}
order = Order[id=2d8e5cc2-26ac-474d-a081-2c71207fd6c5, customerName=Basil]
optionalTimeSlot.toString() = Optional[2022-01-23T14:00-07:00[America/Edmonton]]
{2022-01-23T13:00-07:00[America/Edmonton]=[], 2022-01-23T14:00-07:00[America/Edmonton]=[Order[id=2d8e5cc2-26ac-474d-a081-2c71207fd6c5, customerName=Basil]], 2022-01-23T15:00-07:00[America/Edmonton]=[]}
I was in a job interview and got this question: " Write a function that gets 2 strings s,t that represents 2 hours ( in format HH: MM: SS ). It's known that s is earlier than t.
The function needs to calculate how many hours between the two given hours contains at most 2 digits.
For example- s- 10:59:00, t- 11:00:59 -
Answer- 11:00:00, 11:00:01,11:00:10, 11:00:11.
I tried to do while loops and got really stuck. Unfortunately, I didn't pass the interview.
How can I go over all the hours (every second is a new time) between 2 given hours in java as explained above? Thanks a lot
Java 8 allows you to use LocalTime.
LocalTime time1 = LocalTime.parse(t1);
LocalTime time2 = LocalTime.parse(t2);
The logic would require you to count the amount of different digits in a LocalTime, something like
boolean isWinner(LocalTime current) {
String onlyDigits = DateTimeFormatter.ofPattern("HHmmss").format(current);
Set<Character> set = new HashSet<>();
for (int index = 0; index < onlyDigits.length(); index++) {
set.add(onlyDigits.charAt(index));
}
return set.size() <= 2;
}
You can loop between the times like this
int count = 0;
for (LocalTime current = time1; current.isBefore(time2); current = current.plusSeconds(1)) {
if (isWinner(current)) {
count++;
}
}
That's it.
The question is really more geared towards getting a feel of how you'd approach the problem, and if you know about LocalTime API etc.
This question already has answers here:
Java - Check if array contains 3 consecutive dates
(4 answers)
Closed 5 years ago.
I have an array of unique dates from each time the user completes a task. I want to check if the dates within the array are consecutive from and including todays date.
If the array contains dates: "2017/6/2, 2017/6/3, 2017/6/4, 2017/6/5" then based on today's date being 2017/6/5 the function would return 4 as there are 4 consecutive dates from and including today.
If the array contains dates "2017/6/2, 2017/6/3, 2017/6/4" then it would return 0 as the array does not include today's date. Otherwise the count would be broken upon a non consecutive date.
List<Date> dateList = new ArrayList<Date>();
int count = 0;
Date todayDate = new Date();
for (int i=0; i<dateList.size(); i++){
// Check if dates within the array are consecutive from todayDate, if so then increment count by 1.
}
If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).
Although you can also use JodaTime, it's being discontinued and replaced by the new APIs, do I don't recommend start a new project with joda. Even in joda's website it says: "Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".
As you want to compare just the date (day/month/year), and not the time (hour/minute/second), the best choice is to use the LocalDate class. For java 8, this class is in java.time package, and in ThreeTen Backport, the package is org.threeten.bp. But the classes and methods names are the same.
The code would be like this:
public int count(List<LocalDate> dateList, LocalDate today) {
if (!dateList.contains(today)) { // today is not in the list, return 0
return 0;
}
int count = 0;
LocalDate prev = dateList.get(0); // get first date from list
for (int i = 1; i < dateList.size(); i++) {
LocalDate next = dateList.get(i);
if (prev.plusDays(1).equals(next)) {
// difference between dates is one day
count++;
} else {
// difference between dates is not 1
// Do what? return 0? throw exception?
}
prev = next;
}
return count + 1; // didn't count the first element, adding 1
}
Testing this method:
List<LocalDate> dateList = new ArrayList<>();
dateList.add(LocalDate.of(2017, 6, 2));
dateList.add(LocalDate.of(2017, 6, 3));
dateList.add(LocalDate.of(2017, 6, 4));
dateList.add(LocalDate.of(2017, 6, 5));
LocalDate today = LocalDate.now();
System.out.println(count(dateList, today)); // 4
Another test (when today is not in the list)
List<LocalDate> dateList = new ArrayList<>();
dateList.add(LocalDate.of(2017, 6, 2));
dateList.add(LocalDate.of(2017, 6, 3));
dateList.add(LocalDate.of(2017, 6, 4));
LocalDate today = LocalDate.now();
System.out.println(count(dateList, today)); // 0
Notes:
As it wasn't specified what to do when the days are not consecutive (return 0 or throw exception), I left this part commented. But it should be straightforward to add this to the code
If you want to convert java.util.Date to LocalDate, you can do as follows (using the code of this answer, full explanation is in this link in case you have any questions):
public LocalDate convert(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}
// if your Date has no toInstant method, try this:
public LocalDate convert(Date date) {
return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
}
I understood that you want to check for consecutive days (so, a 1-day difference between the dates). But if you want to check if the previous date is before the next (no matter how many days), you can change the if (prev.plusDays(1).equals(next)) to if (prev.isBefore(next))
I'm not sure if that's the case, but if you want, you can also parse a String directly to a LocalDate (so you don't need to create lots of Date objects), using a DateTimeFormatter:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/M/d");
LocalDate d = LocalDate.parse("2017/6/2", formatter); // 2017-06-02
There are a lot of ways to write it more clear:
Use new Date API;
Use libraries;
But, in such case, with usage of old Date classes, I would do that in such a way:
public static void main(String[] args) {
long millisInDay = TimeUnit.DAYS.toMillis(1);
List<Date> dates = Arrays.asList(new Date("2017/6/2"), new Date("2017/6/3"), new Date("2017/6/4"), new Date("2017/6/5"));
System.out.println(getSequentialNumber(millisInDay, dates));
}
private static int getSequentialNumber(long millisInDay, List<Date> dates) {
int count = 0;
Date now = setMidnight(Calendar.getInstance().getTime());
for (int i = dates.size() - 1; i >= 0; i--) {
Date date = setMidnight(dates.get(i));
if (date.getTime() == now.getTime()) {
count++;
}
now.setTime(now.getTime() - millisInDay);
}
return count;
}
private static Date setMidnight(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.HOUR_OF_DAY, 0);
return calendar.getTime();
}
If I understand the requirement correctly, you have an array of Date objects, ordered by date, and guaranteed not to have two Date objects for the same day, but possibly with gaps between the days. Your goal is to return the length of the maximum sub-array that contains only consecutive days and also includes the current day, or to return 0 if there is no such sub-array. The current day may fall anywhere inside that sub-array, not necessarily at the beginning or end.
It's not clear if you need to support crossing year boundaries, but I'll assume so. I also assume that all the Date objects in the list are for the same time zone which is also the time zone for the device on which you are running. If that's not the case, you should refer to this answer for more information on testing whether two Date objects refer to the same day.
It's fairly simple to do this if you work with Calendar objects instead of Date objects. You don't need any third-party libraries, as both Date and Calendar are parts of the standard Android API. I suggest doing this in two phases: first search for the current date in the array and then scan in both directions for either a gap in the dates or an array boundary. Then just count how far you could go in each direction.
public int getDateSpanCount(List<Date> dateList) {
final int n = dateList.size();
final Calendar today = Calendar.getInstance();
final Calendar other = Calendar.getInstance();
int count = 0;
// First search for today in the date array
int posToday = -1;
for (int i=0; i<n; i++) {
other.setTime(dateList.get(i));
if (areSameDay(today, other)) {
posToday = i;
break;
}
}
// If today is in the list, count the size of the sub-array containing today
if (posToday >= 0) {
count++; // count today, at least
final Calendar probe = Calendar.getInstance();
// scan backwards from position of today's date
for (int prevPos = posToday - 1; prevPos >= 0; prevPos--) {
final Date prev = dateList.get(prevPos);
probe.setTime(prev);
other.add(Calendar.DAY_OF_YEAR, -1);
if (areSameDay(probe, other)) {
count++;
other.setTime(prev);
} else {
break;
}
}
// reset the other time
other.setTime(today.getTime());
// scan forward from position of today's date
for (int nextPos = posToday + 1; nextPos < n; nextPos++) {
final Date next = dateList.get(nextPos);
probe.setTime(next);
other.add(Calendar.DAY_OF_YEAR, 1);
if (areSameDay(probe, other)) {
count++;
other.setTime(next);
} else {
break;
}
}
}
return count;
}
/** Test whether two Calendar objects are set to the same day */
private static boolean areSameDay(Calendar c1, Calendar c2) {
// see discussion above if dates may not all be for the local time zone
return c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR) &&
c1.get(Calendar.DAY_OF_YEAR) == c2.get(Calendar.DAY_OF_YEAR);
}
List of dates are as below (The list can be in any order):
3-Jan to 31-Mar, 2-Apr to 30-Jun, 1-Jul to 30-Sep, 4-Oct to 31-Dec
Current Date is: 19-Feb
Can someone please help me with the logic?
My approach is:
if(the given date should be greater than start date and less than end date){//this gives current quarter}else if(difference of the month of current date from the end date of each object should be less than or equal to 5)
i am hard coding the condition less than 5, which may break if in future the range of date will be of 4 months
Second approach is:
we can sort the list in ascending order and can get the current quarter index by comparing with current date and the next quarter will be of next index. But the complexity will be more.
I tried below code, but it gives only current quarter date. I am not able to get next quarter considering there would be only 3 objects and current date month is feb.
public static List getCurrentQtrOffr(List detail,Date currentDate) throws ParseException{
int currentQuarter = 9999, diff1;
int nextquarter = 9999, diff2;
Detail detail1;
Detail detail2;
Detail detail3 = null;
Detail detail4 = null;
Iterator<Detail> iterator = detail.iterator();
List<Detail> list = new ArrayList<Detail>();
while(iterator.hasNext()){
detail1 = iterator.next();
diff1 = getDiff(currentDate,detail1.startTime());
if(diff1>0){
if(iterator.hasNext()){
detail2 = iterator.next();
}else{
detail2 = null;
}
if(detail2 != null){
diff2 = getDiff(currentDate,detail2.startTime());
if(diff1 < diff2 ){
if(currentQuarter > diff1){
nextquarter = currentQuarter;
currentQuarter = diff1;
//how to assign detail3 before updating it with next minimum value, as if there will be only 3 object and flow comes in this if block then detail4 will be null
detail4=detail3;
detail3=detail1;
}else if(nextquarter > diff1){
nextquarter = diff1;
detail4=detail1;
}
}else{
if(currentQuarter > diff2){
nextquarter = currentQuarter;
currentQuarter = diff2;
detail4=detail3;
detail3=detail1;
}else if(nextquarter > diff2){
nextquarter = diff2;
detail4=detail1;
}
}
}else{
if(currentQuarter > diff1){
nextquarter = currentQuarter;
currentQuarter = diff1;
detail4=detail3;
detail3=detail1;
}else if(nextquarter > diff1){
nextquarter = diff1;
detail4=detail1;
}
}
}else{
System.out.println("skipped "+diff1);
}
}
list.add(detail3);
list.add(detail4);
return list;
}
If the periods are mutually exclusive (not overlapping) the you simply check for the first occurrence where:
The target is equal to or later than the start, and…
The target is before the stop.
This logic follows the Half-Open approach commonly used in date-time work where the beginning is inclusive while the ending is exclusive.
A shorter way of saying "the target is equal to or later than the start" is "not before start". The exclamation mark ! means not in Java syntax.
Boolean periodContainsTarget = ( ! target.isBefore( start ) ) && target.isBefore( stop ) ;
The above logic would be used with LocalDate if you meant date with a year. If you literally meant a month and day without a year, use the MonthDay class. The logic works for both.
Use Period class to represent the span of time between a pair of LocalDate objects. See Tutorial.
You might also find useful the Interval class in the ThreeTen-Extra project that supplements java.time.