我正在嘗試列印任何給定年份的所有周六和周日。但由于某種原因,該程式不會只列印 2022 年的星期六而不是星期五。我嘗試了不同的年份值,但除了 2022 年之外,仍然沒有找到任何值。我在這里做錯了什么???下面是代碼。
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Scanner;
public class JavaDayFinder extends Thread {
int day;
int year;
JavaDayFinder(int day, int year) {
this.day = day;
this.year = year;
}
@Override
public void run() {
Calendar calendar = new GregorianCalendar();
calendar.set(year, Calendar.JANUARY, 1);
calendar.getTime();
calendar.set(Calendar.DAY_OF_WEEK, day);
calendar.getTime();
while (calendar.get(Calendar.YEAR) == year) {
System.out.println(calendar.getTime());
calendar.add(Calendar.DAY_OF_MONTH, 7);
try {
Thread.sleep(250);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
System.out.println("This program prints all the common holidays (Fridays & Saturdays) of any given year.");
System.out.print("Please input the year of which you want to know the holidays: ");
Scanner scan = new Scanner(System.in);
int year = scan.nextInt();
System.out.println("Given year : " year);
System.out.println();
JavaDayFinder friday = new JavaDayFinder(6, year);
JavaDayFinder saturday = new JavaDayFinder(7, year);
friday.start();
saturday.start();
}
}
下面是輸出
This program prints all the common holidays (Fridays & Saturdays) of any given year.
Please input the year of which you want to know the holidays: 2022
Given year : 2022
Sat Jan 01 17:05:56 BDT 2022
Sat Jan 08 17:05:56 BDT 2022
Sat Jan 15 17:05:56 BDT 2022
Sat Jan 22 17:05:56 BDT 2022
Sat Jan 29 17:05:56 BDT 2022
Sat Feb 05 17:05:56 BDT 2022
Sat Feb 12 17:05:56 BDT 2022
Sat Feb 19 17:05:56 BDT 2022
Sat Feb 26 17:05:56 BDT 2022
Sat Mar 05 17:05:56 BDT 2022
Sat Mar 12 17:05:56 BDT 2022
Sat Mar 19 17:05:56 BDT 2022
Sat Mar 26 17:05:56 BDT 2022
Sat Apr 02 17:05:56 BDT 2022
Sat Apr 09 17:05:56 BDT 2022
Sat Apr 16 17:05:56 BDT 2022
Sat Apr 23 17:05:56 BDT 2022
Sat Apr 30 17:05:56 BDT 2022
Sat May 07 17:05:56 BDT 2022
Sat May 14 17:05:56 BDT 2022
Sat May 21 17:05:56 BDT 2022
Sat May 28 17:05:56 BDT 2022
Sat Jun 04 17:05:56 BDT 2022
Sat Jun 11 17:05:56 BDT 2022
Sat Jun 18 17:05:56 BDT 2022
Sat Jun 25 17:05:56 BDT 2022
Sat Jul 02 17:05:56 BDT 2022
Sat Jul 09 17:05:56 BDT 2022
Sat Jul 16 17:05:56 BDT 2022
Sat Jul 23 17:05:56 BDT 2022
Sat Jul 30 17:05:56 BDT 2022
Sat Aug 06 17:05:56 BDT 2022
Sat Aug 13 17:05:56 BDT 2022
Sat Aug 20 17:05:56 BDT 2022
Sat Aug 27 17:05:56 BDT 2022
Sat Sep 03 17:05:56 BDT 2022
Sat Sep 10 17:05:56 BDT 2022
Sat Sep 17 17:05:56 BDT 2022
Sat Sep 24 17:05:56 BDT 2022
Sat Oct 01 17:05:56 BDT 2022
Sat Oct 08 17:05:56 BDT 2022
Sat Oct 15 17:05:56 BDT 2022
Sat Oct 22 17:05:56 BDT 2022
Sat Oct 29 17:05:56 BDT 2022
Sat Nov 05 17:05:56 BDT 2022
Sat Nov 12 17:05:56 BDT 2022
Sat Nov 19 17:05:56 BDT 2022
Sat Nov 26 17:05:56 BDT 2022
Sat Dec 03 17:05:56 BDT 2022
Sat Dec 10 17:05:56 BDT 2022
Sat Dec 17 17:05:56 BDT 2022
Sat Dec 24 17:05:56 BDT 2022
Sat Dec 31 17:05:56 BDT 2022
Process finished with exit code 0
uj5u.com熱心網友回復:
好吧,那是因為對于 Friday,代碼行calendar.set(Calendar.DAY_OF_WEEK, day)導致年份設定為 2021,因此while (calendar.get(Calendar.YEAR) == year)由于條件為 false,因此立即跳過該行。
正如 Ole VV 在評論中已經說過的,你不應該再使用Calendar了。使用LocalDate和DayOfWeek。這是修改后的代碼:
@Override
public void run() {
var dayOfWeek = DayOfWeek.of(day);
LocalDate currDate = LocalDate.of(year, 1, 1)
.with(TemporalAdjusters.nextOrSame(dayOfWeek));
while (currDate.getYear() == year) {
System.out.println(currDate);
currDate = currDate.plusWeeks(1);
try {
Thread.sleep(250);
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
這是發生的事情:
LocalDate.of(year, 1, 1)產生給定年份的 1 月 1 日。TemporalAdjusters.nextOrSame(DayOfWeek)取給定日期并移動到下一個指定的星期幾,如果是指定的星期幾,則停留在 1 月 1 日。在 2022 年的示例中,1 月 1 日是星期六,因此產生的日期將是 2022 年 1 月 7 日,因為那是下一個星期五。- 在回圈中,
currDate.plusWeeks(1)顯然將當前日期增加了一周。(1)
注意:DayOfWeek.MONDAY值為1,DayOfWeek.SUNDAY值為7。(2)但我同意Ole VV 的觀點:你最好使用DayOfWeek常量而不是整數,因為這樣更易讀。
(1) LocalDate本身是不可變的,因此實際上沒有添加任何內容。相反,會回傳一個新實體并添加一周。
(2)好吧,至少DayOfWeek.of(int dayOfWeek)將這些值映射到相應的星期幾。列舉本身不包含特定值,除了列舉的序數值。
uj5u.com熱心網友回復:
tl;博士
使用java.time類、流、lambda 和謂詞的代碼摘錄。
this.datesOfYearforDaysOfWeek(
Year.of( 2023 ) ,
Set.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY )
)
year.atDay( 1 )
.datesUntil(
year
.plusYears( 1 )
.atDay( 1 )
)
.filter(
date -> dows.contains( date.getDayOfWeek() )
)
.toList()
細節
MC Emperor的回答是正確而明智的。為了好玩,我將展示一種不同的方法。雖然我沒有測驗過性能,但可能效率不高。這里我們使用流和 lambda。
我們LocalDate#datesUntil用來獲取LocalDate物件流。請注意,該datesUntil方法使用半開邏輯,其中開頭是包含的,而結尾是排他的。因此,一年從第一年開始,一直到但不包括下一年的第一年。
該類Year代表了一年,使代碼更加清晰和自我記錄。
主要邏輯:
LocalDate firstOfYear = year.atDay( 1 );
List < LocalDate > dates =
firstOfYear
.datesUntil( firstOfYear.plusYears( 1 ) )
.filter(
date -> dows.contains( date.getDayOfWeek() )
)
.toList();
完整的方法。
List < LocalDate > datesOfYearforDaysOfWeek ( final Year year , final Set < DayOfWeek > dows )
{
// Validate inputs.
Objects.requireNonNull( year );
Objects.requireNonNull( dows );
if ( dows.isEmpty() ) { throw new IllegalArgumentException( "Days of week is empty." ); }
// Logic
LocalDate firstOfYear = year.atDay( 1 );
List < LocalDate > dates =
firstOfYear
.datesUntil( firstOfYear.plusYears( 1 ) )
.filter(
date -> dows.contains( date.getDayOfWeek() )
)
.toList();
// Result.
return List.copyOf( dates ); // Effectively a no-op if already an immutable list.
}
用法。
List < LocalDate > dates =
this.datesOfYearforDaysOfWeek(
Year.of( 2023 ) ,
Set.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY )
);
跑的時候。
dates.toString() = [2023-01-01, 2023-01-07, 2023-01-08, 2023-01-14, 2023-01-15, 2023-01-21, 2023-01-22, 2023-01-28, 2023-01-29, 2023-02-04, 2023-02-05, 2023-02-11, 2023-02-12, 2023-02-18, 2023-02-19, 2023-02-25, 2023-02-26, 2023-03-04, 2023-03-05, 2023-03-11, 2023-03-12, 2023-03-18, 2023-03-19, 2023-03-25, 2023-03-26, 2023-04-01, 2023-04-02, 2023-04-08, 2023-04-09, 2023-04-15, 2023-04-16, 2023-04-22, 2023-04-23, 2023-04-29, 2023-04-30, 2023-05-06, 2023-05-07, 2023-05-13, 2023-05-14, 2023-05-20, 2023-05-21, 2023-05-27, 2023-05-28, 2023-06-03, 2023-06-04, 2023-06-10, 2023-06-11, 2023-06-17, 2023-06-18, 2023-06-24, 2023-06-25, 2023-07-01, 2023-07-02, 2023-07-08, 2023-07-09, 2023-07-15, 2023-07-16, 2023-07-22, 2023-07-23, 2023-07-29, 2023-07-30, 2023-08-05, 2023-08-06, 2023-08-12, 2023-08-13, 2023-08-19, 2023-08-20, 2023-08-26, 2023-08-27, 2023-09-02, 2023-09-03, 2023-09-09, 2023-09-10, 2023-09-16, 2023-09-17, 2023-09-23, 2023-09-24, 2023-09-30, 2023-10-01, 2023-10-07, 2023-10-08, 2023-10-14, 2023-10-15, 2023-10-21, 2023-10-22, 2023-10-28, 2023-10-29, 2023-11-04, 2023-11-05, 2023-11-11, 2023-11-12, 2023-11-18, 2023-11-19, 2023-11-25, 2023-11-26, 2023-12-02, 2023-12-03, 2023-12-09, 2023-12-10, 2023-12-16, 2023-12-17, 2023-12-23, 2023-12-24, 2023-12-30, 2023-12-31]
變得更緊湊,但不一定更好。結果相同。
// Logic
List < LocalDate > dates =
year.atDay( 1 )
.datesUntil(
year
.plusYears( 1 )
.atDay( 1 )
)
.filter(
date -> dows.contains( date.getDayOfWeek() )
)
.toList();
執行服務
您可能想要使用執行器服務而不是自己管理執行緒。
將您的任務定義為Callable回傳所需日期串列的 a。構造具有所需年份和星期幾的物件。
class DatesForDayOfWeekTask implements Callable < List < LocalDate > >
{
Year year;
DayOfWeek dow;
public DatesForDayOfWeekTask ( final Year year , final DayOfWeek dow )
{
this.year = year;
this.dow = dow;
}
@Override
public List < LocalDate > call ( ) throws Exception
{
return datesOfYearforDaysOfWeek( this.year , Set.of( this.dow ) );
}
}
示例用法。
System.out.println( "INFO - Demo started. " Instant.now() );
ExecutorService executorService = Executors.newCachedThreadPool();
DatesForDayOfWeekTask saturdayTask = new DatesForDayOfWeekTask( Year.of( 2023 ) , DayOfWeek.SATURDAY );
DatesForDayOfWeekTask sundayTask = new DatesForDayOfWeekTask( Year.of( 2023 ) , DayOfWeek.SUNDAY );
Future < List < LocalDate > > saturdayFuture = executorService.submit( saturdayTask );
Future < List < LocalDate > > sundayFuture = executorService.submit( sundayTask );
System.out.println( "INFO Tasks submitted. Please wait. " Instant.now() );
try { Thread.sleep( Duration.ofSeconds( 10 ).toMillis() ); } catch ( InterruptedException e ) { throw new RuntimeException( e ); }
this.shutdownAndAwaitTermination( executorService );
try
{
System.out.println( "saturdayFuture.get() = " saturdayFuture.get() );
System.out.println( "sundayFuture.get() = " sundayFuture.get() );
}
catch ( InterruptedException e ) { throw new RuntimeException( e ); }
catch ( ExecutionException e ) { throw new RuntimeException( e ); }
System.out.println( "INFO - Demo ended. " Instant.now() );
跑的時候。
INFO - Demo started. 2022-09-28T00:38:58.460930Z
INFO Tasks submitted. Please wait. 2022-09-28T00:38:58.469034Z
saturdayFuture.get() = [2023-01-07, 2023-01-14, 2023-01-21, 2023-01-28, 2023-02-04, 2023-02-11, 2023-02-18, 2023-02-25, 2023-03-04, 2023-03-11, 2023-03-18, 2023-03-25, 2023-04-01, 2023-04-08, 2023-04-15, 2023-04-22, 2023-04-29, 2023-05-06, 2023-05-13, 2023-05-20, 2023-05-27, 2023-06-03, 2023-06-10, 2023-06-17, 2023-06-24, 2023-07-01, 2023-07-08, 2023-07-15, 2023-07-22, 2023-07-29, 2023-08-05, 2023-08-12, 2023-08-19, 2023-08-26, 2023-09-02, 2023-09-09, 2023-09-16, 2023-09-23, 2023-09-30, 2023-10-07, 2023-10-14, 2023-10-21, 2023-10-28, 2023-11-04, 2023-11-11, 2023-11-18, 2023-11-25, 2023-12-02, 2023-12-09, 2023-12-16, 2023-12-23, 2023-12-30]
sundayFuture.get() = [2023-01-01, 2023-01-08, 2023-01-15, 2023-01-22, 2023-01-29, 2023-02-05, 2023-02-12, 2023-02-19, 2023-02-26, 2023-03-05, 2023-03-12, 2023-03-19, 2023-03-26, 2023-04-02, 2023-04-09, 2023-04-16, 2023-04-23, 2023-04-30, 2023-05-07, 2023-05-14, 2023-05-21, 2023-05-28, 2023-06-04, 2023-06-11, 2023-06-18, 2023-06-25, 2023-07-02, 2023-07-09, 2023-07-16, 2023-07-23, 2023-07-30, 2023-08-06, 2023-08-13, 2023-08-20, 2023-08-27, 2023-09-03, 2023-09-10, 2023-09-17, 2023-09-24, 2023-10-01, 2023-10-08, 2023-10-15, 2023-10-22, 2023-10-29, 2023-11-05, 2023-11-12, 2023-11-19, 2023-11-26, 2023-12-03, 2023-12-10, 2023-12-17, 2023-12-24, 2023-12-31]
INFO - Demo ended. 2022-09-28T00:39:08.480522Z
完整的示例代碼。
package work.basil.example.days;
import java.time.*;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.*;
public class App
{
public static void main ( String[] args )
{
App app = new App();
// app.demo();
app.demoThreaded();
}
private void demo ( )
{
List < LocalDate > dates =
this.datesOfYearforDaysOfWeek(
Year.of( 2023 ) ,
Set.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY )
);
System.out.println( "dates.toString() = " dates );
}
List < LocalDate > datesOfYearforDaysOfWeek ( final Year year , final Set < DayOfWeek > dows )
{
// Validate inputs.
Objects.requireNonNull( year );
Objects.requireNonNull( dows );
if ( dows.isEmpty() ) { throw new IllegalArgumentException( "Days of week is empty." ); }
// Logic
List < LocalDate > dates =
year.atDay( 1 )
.datesUntil(
year
.plusYears( 1 )
.atDay( 1 )
)
.filter(
date -> dows.contains( date.getDayOfWeek() )
)
.toList();
// Result.
return List.copyOf( dates ); // Effectively a no-op if already an immutable list.
}
private void demoThreaded ( )
{
System.out.println( "INFO - Demo started. " Instant.now() );
ExecutorService executorService = Executors.newCachedThreadPool();
DatesForDayOfWeekTask saturdayTask = new DatesForDayOfWeekTask( Year.of( 2023 ) , DayOfWeek.SATURDAY );
DatesForDayOfWeekTask sundayTask = new DatesForDayOfWeekTask( Year.of( 2023 ) , DayOfWeek.SUNDAY );
Future < List < LocalDate > > saturdayFuture = executorService.submit( saturdayTask );
Future < List < LocalDate > > sundayFuture = executorService.submit( sundayTask );
System.out.println( "INFO Tasks submitted. Please wait. " Instant.now() );
try { Thread.sleep( Duration.ofSeconds( 10 ).toMillis() ); } catch ( InterruptedException e ) { throw new RuntimeException( e ); }
this.shutdownAndAwaitTermination( executorService );
try
{
System.out.println( "saturdayFuture.get() = " saturdayFuture.get() );
System.out.println( "sundayFuture.get() = " sundayFuture.get() );
}
catch ( InterruptedException e ) { throw new RuntimeException( e ); }
catch ( ExecutionException e ) { throw new RuntimeException( e ); }
System.out.println( "INFO - Demo ended. " Instant.now() );
}
class DatesForDayOfWeekTask implements Callable < List < LocalDate > >
{
Year year;
DayOfWeek dow;
public DatesForDayOfWeekTask ( final Year year , final DayOfWeek dow )
{
this.year = year;
this.dow = dow;
}
@Override
public List < LocalDate > call ( ) throws Exception
{
return datesOfYearforDaysOfWeek( this.year , Set.of( this.dow ) );
}
}
// Boilerplate code taken from `ExecutorService` interface Javadoc, and slightly modified.
private void shutdownAndAwaitTermination ( ExecutorService executorService )
{
executorService.shutdown(); // Disable new tasks from being submitted
try
{
// Wait a while for existing tasks to terminate
if ( ! executorService.awaitTermination( 60 , TimeUnit.SECONDS ) )
{
executorService.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if ( ! executorService.awaitTermination( 60 , TimeUnit.SECONDS ) )
{ System.err.println( "Pool did not terminate" ); }
}
}
catch ( InterruptedException ex )
{
// (Re-)Cancel if current thread also interrupted
executorService.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
}
uj5u.com熱心網友回復:
解釋:
如果 1 月 1 日是星期六,這意味著該周的星期五將比 1 月 1 日早 1 天,即 12 月 31 日。當您將以下欄位設定為星期五時,它將值設定為 12 月 31 日,并且由于您的 while 條件,它不執行回圈。
calendar.set(Calendar.DAY_OF_WEEK, day);
此代碼不適用于邊緣情況,即從星期六開始的任何一年都不會列印星期五。例如 2011 年、2028 年等。
以下方法設定為每月的第一個星期五/星期六/任何作業日:
private void setNextAvailableDay(Calendar calendar, int day) {
Date currTime = calendar.getTime();
calendar.set(Calendar.DAY_OF_WEEK, day);
if(currTime.after(calendar.getTime()))
calendar.add(Calendar.DAY_OF_MONTH, 7);
}
calendar.set(Calendar.DAY_OF_WEEK, day);
// can be replaced by
setNextAvailableDay(calendar, day)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/510304.html
標籤:爪哇日期
