Reputation: 1829
I want to create a "select", that when selecting a year in another "select", I load all the weeks of that year, from Monday to Friday:
Example, if I select 2018 my "select" would be something like this.
1 - 01/01/18 - 07/01/18
2 - 01/08/18 - 01/14/18
3 - 15/01/18 - 01/21/10
......
52 - 12/24/18 - 12/30/18
The data was prepared in the back-end with java. To then send it as an array of string to the front-end
Upvotes: 0
Views: 87
Reputation: 340108
The modern solution uses java.time classes. These supplanted the terribly flawed legacy classes such as Date
& Calendar
.
Determine the first day of year. And the first day of the following year, as our limit.
Year year = Year.of( 2018 );
LocalDate firstOfYear = year.atDay( 1 );
LocalDate firstOfFollowingYear = year.plusYears( 1 ).atDay( 1 );
Use a TemporalAdjuster
to move through time. The TemporalAdjusters
class (note the plural) happens to offer an adjuster implementation for our needs, previousOrSame
. Use that to move back in time to get a Monday, if the 1st of year is not already Monday.
TemporalAdjuster adjuster = TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY );
LocalDate firstMondayOfYear = firstOfYear.with( adjuster );
Define a list to hold our weekly report.
List < String > weeks = new ArrayList <>( 53 );
Define a formatter to generate the text for our weekly report. The DateTimeFormatter
class can automatically localize, so we need not hard-code a specific format.
Locale locale = Locale.forLanguageTag( "es-ES" ); // Spain locale.
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( locale );
Loop through the weeks of the year. We increment one week at a time, until hitting the following year.
int nthWeekOfYear = 0;
LocalDate localDate = firstMondayOfYear;
while ( localDate.isBefore( firstOfFollowingYear ) ) {
nthWeekOfYear++;
String output = nthWeekOfYear + " - " + localDate.format( formatter ) + " - " + localDate.plusDays( 6 ); // Using Fully-Closed weeks, where both beginning and end are inclusive. In contrast to Half-Open.
weeks.add( output );
// Set up next loop.
localDate = localDate.plusWeeks( 1 );
}
Convert from a List
to an array, per your directions in the Question.
String[] results = weeks.toArray( new String[ weeks.size() ] );
Dump to console.
System.out.println( "results = " + Arrays.toString( results ) );
We could rewrite this code by using streams and lambdas. This requires Java 9+.
The LocalDate#datesUntil
method produces a Stream
of LocalDate
objects.
While I do not necessarily recommend this code, I found it interesting that we can write the entire routine as a one-liner.
int inputYear = 2018;
List < String > weeks =
Year
.of( inputYear )
.atDay( 1 )
.with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) )
.datesUntil( Year.of( inputYear ).plusYears( 1 ).atDay( 1 ) , Period.ofWeeks( 1 ) )
.map( localDate -> localDate.format( DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( Locale.forLanguageTag( "es-ES" ) ) ) + " - " + localDate.plusDays( 6 ).format( DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( Locale.forLanguageTag( "es-ES" ) ) ) )
.toList(); // Before Java 16, change to .collect( Collectors.toList()); or .collect( Collectors.toUnmodifiableList());
When run.
weeks = [1/1/18 - 7/1/18, 8/1/18 - 14/1/18, 15/1/18 - 21/1/18, 22/1/18 - 28/1/18, 29/1/18 - 4/2/18, 5/2/18 - 11/2/18, 12/2/18 - 18/2/18, 19/2/18 - 25/2/18, 26/2/18 - 4/3/18, 5/3/18 - 11/3/18, 12/3/18 - 18/3/18, 19/3/18 - 25/3/18, 26/3/18 - 1/4/18, 2/4/18 - 8/4/18, 9/4/18 - 15/4/18, 16/4/18 - 22/4/18, 23/4/18 - 29/4/18, 30/4/18 - 6/5/18, 7/5/18 - 13/5/18, 14/5/18 - 20/5/18, 21/5/18 - 27/5/18, 28/5/18 - 3/6/18, 4/6/18 - 10/6/18, 11/6/18 - 17/6/18, 18/6/18 - 24/6/18, 25/6/18 - 1/7/18, 2/7/18 - 8/7/18, 9/7/18 - 15/7/18, 16/7/18 - 22/7/18, 23/7/18 - 29/7/18, 30/7/18 - 5/8/18, 6/8/18 - 12/8/18, 13/8/18 - 19/8/18, 20/8/18 - 26/8/18, 27/8/18 - 2/9/18, 3/9/18 - 9/9/18, 10/9/18 - 16/9/18, 17/9/18 - 23/9/18, 24/9/18 - 30/9/18, 1/10/18 - 7/10/18, 8/10/18 - 14/10/18, 15/10/18 - 21/10/18, 22/10/18 - 28/10/18, 29/10/18 - 4/11/18, 5/11/18 - 11/11/18, 12/11/18 - 18/11/18, 19/11/18 - 25/11/18, 26/11/18 - 2/12/18, 3/12/18 - 9/12/18, 10/12/18 - 16/12/18, 17/12/18 - 23/12/18, 24/12/18 - 30/12/18, 31/12/18 - 6/1/19]
A little more reasonable would be extracting the formatter and the Year
.
Locale locale = Locale.forLanguageTag( "es-ES" ); // Spain locale.
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( locale );
Year year = Year.of( 2018 );
List < String > weeks =
year
.atDay( 1 )
.with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) )
.datesUntil( year.plusYears( 1 ).atDay( 1 ) , Period.ofWeeks( 1 ) )
.map( localDate -> localDate.format( formatter ) + " - " + localDate.plusDays( 6 ).format( formatter ) )
.toList(); // Before Java 16, change to .collect( Collectors.toList()); or .collect( Collectors.toUnmodifiableList());
If your definition of week complies with the ISO 8601 definition of week:
… then I suggest adding the ThreeTen-Extra
library to your project to utilize the YearWeek
class.
Upvotes: 1
Reputation: 1829
public class Weeks {
public static void main(String[] args) {
int year = 2018;
int weeks = getNumWeeksForYear(year);
for (int i = 1; i < weeks; i++) {
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(Calendar.WEEK_OF_YEAR, i);
calendar.set(Calendar.YEAR, year);
Date monday = calendar.getTime();
calendar.add(Calendar.DATE, 6);
Date sunday = calendar.getTime();
System.out.println("week" + i);
System.out.println(monday);
System.out.println(sunday);
}
}
public static int getNumWeeksForYear(int year) {
Calendar c = Calendar.getInstance();
c.set(year, 0, 1);
return c.getMaximum(Calendar.WEEK_OF_YEAR);
}
}
Upvotes: 0