JavaはYYYYMMDD形式で1年のすべての稼働日を取得します


8

私の日曜日の課題は、特定の年の稼働日を取得してCSVなどのファイルに保存することです。

次のコードがあり、私が直面している問題は、特定の形式で日付を印刷する方法です。つまり、コードは現在、Sat Jan 19 00:00:00 CET 2019のようなものを印刷するため、YYYYMMDDです。

また、週末を除外できる場合、および一般的にJava 8ではるかに短いコードを記述するより良い方法がある場合。

import java.io.*;
import java.util.*;
import java.text.SimpleDateFormat;

public class DatesInYear
{

    public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");

    public static void main (String[] args) throws java.lang.Exception
    {

        Date dt = new Date();
        System.out.println(dt);

        List<Date> dates = printDates("20190101","20191231");


        Collections.reverse(dates);
        System.out.println(dates.size());
        for(Date date:dates)
        {
            SimpleDateFormat format1 = new SimpleDateFormat("yyyyMMdd");
            System.out.println(format1.format(date));

        }
    }
    public static List<Date> printDates(String fromDate, String toDate)
    {
        ArrayList<Date> dates = new ArrayList<Date>();

        try {

            Calendar fromCal = Calendar.getInstance();
            fromCal.setTime(dateFormat .parse(fromDate));

            Calendar toCal = Calendar.getInstance();
            toCal.setTime(dateFormat .parse(toDate));

            while(!fromCal.after(toCal))
            {
                dates.add(fromCal.getTime());
                fromCal.add(Calendar.DATE, 1);
            }


        } catch (Exception e) {
            System.out.println(e);
        }
        return dates;
    }
}

1
ただしないでSystem.out.println(date)、使用dateFormatあなたはすでにあなたがそれを必要とする方法でそれをフォーマットする作りました。
ティロ

2
String date1 = format1.format(date);その後、あなたは何もしませんdate1。しかし、あなたは正しい軌道に乗っています。
Federico klez Culloca

1
Calendar曜日の確認にも使用できます。
ティロ

1
Javaのバージョンは何ですか?8か9+?
ernest_k

1
私はJava 8を使用しています
JavaMan

回答:


3

あなたの問題に対する2つのわずかに異なるテイクがあります:

import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class DatesInYear {

    public static void main(final String[] args) throws Exception {

        listWorkingDays(2020).forEach(System.out::println);
    }

    private static List<LocalDate> listWorkingDays(final int year) {

        IntStream
            .rangeClosed(1,      LocalDate.ofYearDay(year + 1, 1).minusDays(1).getDayOfYear())
            .mapToObj   (day  -> LocalDate.ofYearDay(year, day))
            .filter     (date -> date.getDayOfWeek().getValue() <= 5)
            .forEach    (System.out::println);

        return IntStream
            .rangeClosed(1,      LocalDate.ofYearDay(year + 1, 1).minusDays(1).getDayOfYear())
            .mapToObj   (day  -> LocalDate.ofYearDay(year, day))
            .filter     (date -> date.getDayOfWeek().getValue() <= 5)
            .collect    (Collectors.toList());
    }
}

デイブ、ありがとう。これは本当にスマートに見えます。私はいくつかの単体テストをまとめているだけですが、本当に面白いようです。乾杯
JavaMan

最初の目的は何IntStreamですか?日付が2回表示されます。または、なぜ最初のものだけを残してIntStream、戻り値の型をvoidに変更しないのですか?気になるだけです。
セバスチャンI.

私が述べたように、それは問題を2つ取るだけです。JavaManは好きなものを選ぶことができます。:-)
デイブ・ザ・デーン

これらの新しいイディオムは、一般的にineffecientているように私にはありません、LocalDate.ofYearDayは毎回新しいインスタンスを作成します github.com/frohoff/jdk8u-jdk/blob/...、あなたは非常にメソッドを使用してこのコードを置けば、それは文句を言わないこと最も効率的です。
レオ

7

2020年なので、実際にはjava.time.*API を採用する必要があります。

「営業」日を日付に変換する本当にきちんとした方法があると私は確信していますが、私はブルートフォースメソッドに行きました...

LocalDate ld = LocalDate.of(2020, Month.JANUARY, 1);
LocalDate endDate = ld.plusYears(1);

// You don't "have" to put into a list, but I like to seperate my
// code responsbilities ;)
List<LocalDate> workDays = new ArrayList<>(365);
System.out.println(endDate);
while (ld.isBefore(endDate)) {
    // This would be a good place for a delegate to determine if we want the specific day
    // as it could then take into account public holidays
    if (ld.getDayOfWeek() == DayOfWeek.SATURDAY || ld.getDayOfWeek() == DayOfWeek.SUNDAY) {
        // NOOP
    } else {
        workDays.add(ld);
    }
    ld = ld.plusDays(1);
}

次に、単純にa DateTimeFormatterを使用して、を必要な形式にフォーマットできLocalDateます。たとえば...

DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyyMMdd");
List<String> formats = workDays.stream().map(value -> value.format(format)).collect(Collectors.toList());

for (String value : formats) {
    System.out.println(value);
}


@Eugeneだから-それは本質的に私がとにかくやったことの略記バージョンです-知っておきたい
MadProgrammer

確かに、そうです、最終的にはそうLongStream.rangeClosed(0, steps).mapToObj( n -> this.plusMonths(months * n).plusDays(days * n));です...しかし、あなたのコードに関してArrayList240、おおよその見積もりのサイズになる可能性があり360 - 2 * 40ます。さらに、ある場合は次のif(condition) {NO-OP} else {OP}ように変更する必要がありますif(!condition){OP}
ユージーン

1
わかりました。
ユージーン

1
@Eugeneフィードバックのようにthough
MadProgrammer

7
    Set<DayOfWeek> weekend = EnumSet.of(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY);
    LocalDate.of(2019, Month.JANUARY, 1)
             .datesUntil(LocalDate.of(2020, Month.DECEMBER, 31), Period.ofDays(1))
             .filter(x -> !weekend.contains(x.getDayOfWeek()))
             .forEachOrdered(System.out::println);

2

Java 8と最新の日時APIを使用して日付範囲のすべての平日を表示する明快な方法は次のとおりです。

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        List<LocalDate> dates = getDates("2019-01-01", "2019-12-31");
        for (LocalDate date : dates) {
            System.out.println(DateTimeFormatter.BASIC_ISO_DATE.format(date));
        }
    }

    public static List<LocalDate> getDates(String fromDate, String toDate) {
        LocalDate startDate = LocalDate.parse(fromDate);
        LocalDate endDate = LocalDate.parse(toDate).plusDays(1);
        long range = ChronoUnit.DAYS.between(startDate, endDate);
        return Stream.iterate(startDate, date -> date.plusDays(1)).limit(range)
                .filter(d -> !(d.getDayOfWeek() == DayOfWeek.SATURDAY || d.getDayOfWeek() == DayOfWeek.SUNDAY))
                .collect(Collectors.toList());
    }
}

出力:

20190101
20190102
20190103
20190104
20190107
20190108
...
...
...
20191226
20191227
20191230
20191231

1
非常に素晴らしい。変更する2つの点ChronoUnit.DAYS.between(startDate, endDate)は、毎回再計算するのではなく、変数に格納することです。また、Java 9+コードの場合は、の.takeWhile(endDate::isAfter)代わりに使用できますlimit()。:また、あなたの代わりに曜日名を比較の列挙比較を使用することができます!(d -> d.getDayOfWeek() == DayOfWeek.SUNDAY || d.getDayOfWeek() == DayOfWeek.SUNDAY)
ernest_k

正のフィードバックをありがとう、@ ernest_k。あなたのコメントは私にとって大きな意味があります。あなたが提案したように私はそれを改善します。
Arvind Kumar Avinash

@ernest_k-私はあなたの最初のコメントを組み込みましたが、OPがJava 8を使用しているとOPが述べたため、2番目のコメントは読者に組み込んでもらいました。また、JVMはChronoUnit.DAYS.between(startDate, endDate)毎回再計算するのではなく最適化することを理解していました。それが正しくなかったかどうか理解するためにあなたの助けが必要です。
Arvind Kumar Avinash


私はどちらがより堅牢d.getDayOfWeek().name().equals("SATURDAY")d.getDayOfWeek() == DayOfWeek.SATURDAYなるかを実行するポイントが
わかりません-IMHO

1
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
    List<LocalDate> dates = getDates("2019-01-01", "2019-12-31");
    for (LocalDate date : dates) {
        System.out.println(DateTimeFormatter.BASIC_ISO_DATE.format(date));
    }
}

public static List<LocalDate> getDates(String fromDate, String toDate) {
    LocalDate startDate = LocalDate.parse(fromDate);
    LocalDate endDate = LocalDate.parse(toDate).plusDays(1);
    long range = ChronoUnit.DAYS.between(startDate, endDate);
    return Stream.iterate(startDate, date -> date.plusDays(1)).limit(range)
            .filter(d -> !(d.getDayOfWeek() == DayOfWeek.SATURDAY || d.getDayOfWeek() == DayOfWeek.SUNDAY))
            .collect(Collectors.toList());
}

}


コードは美しいです。なぜ、どのようにタスクを実行するのかについての説明を追加することもできます。
Ole VV

-1

これを試して:

// Java 8を使用

 DateTimeFormatter oldPattern = DateTimeFormatter
        .ofPattern("yyyy-MM-dd HH:mm:ss");
    DateTimeFormatter newPattern = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    LocalDateTime datetime = LocalDateTime.parse(input, oldPattern);
    output = datetime.format(newPattern);

    System.out.println("old format date: " + input);
    System.out.println("new format date : " + output);

素晴らしいコードですが、質問との関係が私からずれていますか?
Ole VV

ここでは例としてmycodeを指定しただけで、彼は私が使用した方法に従うことができます。しかし、彼だけが私のコードから新しい日付形式を取得する必要があります。
Raghavendra
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.