web-dev-qa-db-ja.com

Java:日付を減算する最も簡単な方法

日付である必要がある2つのフィールドを持つクラスを作成しました。start_dateおよびdate_passed。私はJavaで日付をYYYY MM DD簡単な日付の減算を可能にする形式、およびたとえば将来の日付を「構成」する機能。

私がやりたいことの例...

library.circulate_book("Chemistry", **start date here**) //actual date or random date
library.pass_book("Chemistry", **Date Passed here**) //random date such as 5 days after start date
int days_had = Date_Passed - start_date

これまでのところ、CalendarsとDateクラスを使用して日付をフォーマットする方法をたくさん見つけましたが、ほとんどの日付が文字列であると考えるとうまくいくように見えるものをまだ見つけていません。提案/小さな例は大歓迎です!また、例へのリンクは素晴らしいでしょう!

13
Bob

tl; dr

日数を加算/減算して、ある日付から別の日付に移動すること。

LocalDate.now(
    ZoneId.of( "Pacific/Auckland" ) 
)
.minusDays( 5 )

2つの日付の間に経過した日数、月数、および年数を計算します。

Period.between( start , stop )

解析

まず、文字列入力を日付時刻オブジェクトに解析する必要があります。次に、これらのオブジェクトで ビジネスロジック を事前に作成します。

日付時刻の値を文字列として考えるのをやめましょう。コード内で日時オブジェクトを操作します。その日時オブジェクトの文字列表現を使用して、ユーザーまたは他のアプリとデータを交換します。

Java 8以降では、 Java.time フレームワークを使用します。 チュートリアル を参照してください。

時刻なしで日付のみが必要なため、 LocalDate クラスを使用できます。

そのファンキーなダブルコロン構文は method reference であり、他のコードによってどのメソッドが呼び出されるべきかを示す方法です。

String input = "2015 01 02";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "yyyy MM dd" );
LocalDate localDate = formatter.parse ( input , LocalDate :: from );

現在の日付

今日の日付を特定するにはタイムゾーンが必要です。どのような場合でも、日付はゾーンごとに世界中で異なります。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalDate todayTunis = LocalDate.now( z ) ;

JVMの現在のデフォルトのタイムゾーンが必要な場合は、ZoneId.systemDefault

日付の減算

これはStackOveflow.comで何度も取り上げられてきました。たとえば、 Java calendar? を使用して日付からX日を引く方法。詳細については、 this one by me などの他の回答を参照してください。 =および これは私による 詳細:ヒント: "elapsed"は重要な検索ワードです。

簡単に言えば、 Period を使用して、標準の日、月、年の数を定義します。

LocalDate weekLater = localDate.plusDays ( 7 );
Period period = Period.between ( localDate , weekLater );
Integer daysElapsed = period.getDays ();

コンソールにダンプします。

System.out.println ( "localDate: " + localDate + " to " + weekLater + " in days: " + daysElapsed );

localDate:2015-01-02から2015-01-09日:7

Periodは1日のみで機能するという制限に注意してください。つまり、時刻のない日付のみの値です。これがこの質問に必要なものです。日時の値(ZonedDateTimeオブジェクト)がある場合は、上記のリンクされた質問/回答に記載されているように、 ThreeTen-Extra プロジェクトのDaysクラスを使用します。

18
Basil Bourque

Java-8でこれを行う最良の方法は、バジルブルクの欠陥のある答えではなく、このアプローチです:

_String startDate = "2016 01 02";
String passedDate = "2016 02 29";

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd");
LocalDate date1 = LocalDate.parse(startDate, formatter);
LocalDate date2 = LocalDate.parse(passedDate, formatter);

long elapsedDays = ChronoUnit.DAYS.between(date1, date2);
System.out.println(elapsedDays); // 58 (correct)
_

推奨されるJava.time.Period.getDays()の使用は危険であり、経過時間が1か月を超えるとすぐに間違っていることがよくあります。 Period全体がP1M27Dであるため、このコードは実質的に経過日数の一部のみを照会します(経過月もあります)。

_System.out.println(Period.between(date1, date2).getDays()); // 27 (WRONG!!!)
_

クラス_Java.util.Date_、GregorianCalendarなどを使用した満足のいく解決策を見つけるのは困難です。 Tacktheritrixの答えを使用することはできますが、計算されるという事実に注意する必要があります経過日数のカウントは、_Java.util.Date_のサブ日部分によって異なる場合があり、夏時間の切り替え(世界の多くの地域で時計が1時間ジャンプする)を無視するため、信頼性も低くなります。

サイドノート:少なくとも8つの外部ライブラリもあなたの問題に対する良い答えを提供します。ただし、Java-8をまだ使用していない場合を除き、単純なユースケースでは追加のライブラリの埋め込みは正当化されません。 2つの日付間の経過日数をカウントする代替ソリューションは、Java-8の場合よりも簡単ではありません-似ているだけです。 Basil BourqueのJava-8関連の回答を受け入れたので、実際にJava-8を使用していると思いますので、他のライブラリの問題を解決する方法についての回答は省略します。

12
Meno Hochschild

Java 8 date apiまたはjoda、新しい発明は必要ありません。

ここにいくつかの例を見つけることができます: http://examples.javacodegeeks.com/core-Java/java-8-datetime-api-tutorial/

2
Emerson Cod

Calendarを使用した答えは次のとおりです。

Calendar cal = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();

cal2.setTime(cal.getTime());
cal2.add(Calendar.DAY_OF_YEAR, 5);
System.out.println((cal2.getTimeInMillis() - cal.getTimeInMillis()) / (1000d * 60 * 60 * 24));
1
Evan LaHurd

古いJavaでスタックしている場合は、SimpleDateFormatを使用できます。

    //For substraction
    long differenceInMillis = date1.getTime() - date2.getTime();

    //Date Format
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy MM dd");
    String dateAsString = dateFormat.format(date1); //To get a text representation
    Date dateParsed = dateFormat.parse(dateAsString); //To get it back as date
0
liloargana