Javaカレンダーを使用して日付からX日を引く方法は?


180

Javaカレンダーを使用して日付からX日を減算する簡単な方法を知っている人はいますか?

Javaで日付からX日を直接減算できる関数を見つけることができませんでした。誰かが私を正しい方向に向けることができますか?


参考までに、java.timeクラスに取って代わった、java.util.Calendar今ではレガシーなどの厄介な古い日時クラス。Oracleによるチュートリアルを参照してください。
バジルブルク2017

回答:


309

ここのドキュメントから取得

カレンダーのルールに基づいて、指定された時間を特定のカレンダーフィールドに加算または減算します。たとえば、カレンダーの現在の時刻から5日を引くには、次のように呼び出してそれを実現できます。

Calendar calendar = Calendar.getInstance(); // this would default to now
calendar.add(Calendar.DAY_OF_MONTH, -5).

1
期待したとおりに回転するとは限らないので、注意してください。
カーソン2008年

1
この回答には多くの賛成票がありますが、使用しても安全ですか?またはこれがより良い:stackoverflow.com/a/10796111/948268
Kuldeep Jain

44
あなたがCalendar.DAY_OF_MONTH望むように月間のロールを処理しないので、この場合は使用しません。Calendar.DAY_OF_YEAR代わりに使用
アルゴリズム

4
これは、あなたがそれを追加している明らかにする場合、安全でなければならない問題ではない場合、それのDAY_OF_MONTHまたはDAY_OF_YEAR stackoverflow.com/q/14065198/32453
rogerdpack

@carsonこのアプローチの問題のいくつかは何ですか?
tatmanblue 2017

38

addメソッドを使用して、負の数を渡すことができます。ただし、Calendar次のようなクラスを使用しない簡単なメソッドを作成することもできます。

public static void addDays(Date d, int days)
{
    d.setTime( d.getTime() + (long)days*1000*60*60*24 );
}

これは日付のタイムスタンプ値(エポックからのミリ秒)を取得し、適切なミリ秒数を追加します。減算を行うには、daysパラメーターに負の整数を渡すことができます。これは、「適切な」カレンダーソリューションよりも簡単です。

public static void addDays(Date d, int days)
{
    Calendar c = Calendar.getInstance();
    c.setTime(d);
    c.add(Calendar.DATE, days);
    d.setTime( c.getTime().getTime() );
}

これらのソリューションDateはどちらも、まったく新しいを返すのではなく、パラメータとして渡されたオブジェクトを変更することに注意してくださいDate。どちらの関数も、必要に応じて、他の方法で簡単に変更できます。


3
.setTimeと.addがCalendarの静的メソッドであるとは思わないでください。インスタンス変数cを使用する必要があります。
エドワード

@エドワード:あなたは正しいです。私の間違いを指摘してくれてありがとう。コードが修正され、正しく機能するようになりました。
Eli Courtwright、2011

3
それが失敗することがありleapyear日を扱うときに、たとえば、第一の方法には注意してください:stackoverflow.com/a/1006388/32453
rogerdpack

参考までに、java.timeクラスに取って代わった、java.util.Calendar今ではレガシーなどの厄介な古い日時クラス。Oracleによるチュートリアルを参照してください。
バジルブルク2017

36

Ansonの答えは単純なケースでは問題なく機能しますが、より複雑な日付の計算を行う場合は、Joda Timeを確認することをお勧めします。それはあなたの人生をはるかに容易にします。

あなたができるジョーダタイムの参考情報

DateTime dt = new DateTime();
DateTime fiveDaysEarlier = dt.minusDays(5);

1
@ ShahzadImam、DateTimeFormatをチェックしてください。これにより、任意の形式を使用して、DateTimeインスタンスを文字列に変換できます。java.text.DateFormatクラスとよく似ています。
マイクデッキ

1
Java 8以降、java.timedocs.oracle.com
javase

FYI、ジョダタイムプロジェクトは、今でメンテナンスモードへの移行を助言チームと、java.timeのクラス。Oracleによるチュートリアルを参照してください。
バジルブルク2017

19

tl; dr

LocalDate.now().minusDays( 10 )

タイムゾーンを指定する方がよい。

LocalDate.now( ZoneId.of( "America/Montreal" ) ).minusDays( 10 )

細部

java.util.Date/ などのJavaの初期バージョンにバンドルされていた古い日時クラスは、.Calendar面倒で混乱を招き、欠陥があることが判明しています。それらを避けてください。

java.time

Java 8以降は、これらの古いクラスを新しいjava.timeフレームワークに置き換えます。チュートリアルを参照してください。JSR 310によって定義され、Joda- Timeに触発され、ThreeTen-Extraプロジェクトによって拡張されました。ThreeTen-Backportプロジェクトは、クラスをJava 6および7にバックポートします。ThreeTenABPプロジェクトからAndroidへ。

質問はあいまいで、日付のみを要求するのか日時を要求するのかは明確ではありません。

LocalDate

時刻のみなしの日付のみの場合は、LocalDateクラスを使用します。「今日」などの日付を決定する際には、タイムゾーンが重要です。

LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
LocalDate tenDaysAgo = today.minusDays( 10 );

ZonedDateTime

日時を意味する場合は、Instantクラスを使用してUTCのタイムラインの瞬間を取得します。そこから、タイムゾーンに合わせてZonedDateTimeオブジェクトを取得します。

Instant now = Instant.now();  // UTC.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
ZonedDateTime tenDaysAgo = zdt.minusDays( 10 );

モダンとレガシーの両方のJavaの日時タイプの表。


java.timeについて

java.timeのフレームワークは、Java 8に組み込まれており、後にされています。これらのクラスは面倒古い取って代わるレガシーのような日付時刻クラスをjava.util.DateCalendar、& SimpleDateFormat

ジョダタイムプロジェクトは、今でメンテナンスモードへの移行をアドバイスjava.timeのクラス。

詳細については、Oracleチュートリアルを参照してください。また、スタックオーバーフローで多くの例と説明を検索してください。仕様はJSR 310です。

java.timeオブジェクトをデータベースと直接交換することができます。JDBC 4.2以降に準拠したJDBCドライバーを使用します。文字列もクラスも必要ありません。java.sql.*

java.timeクラスはどこで入手できますか?

  • Java SE 8 Java SE 9 Java SE 10以降
    • 内蔵。
    • 実装がバンドルされた標準Java APIの一部。
    • Java 9では、いくつかのマイナーな機能と修正が追加されています。
  • Java SE 6および Java SE 7
    • java.time機能の多くは、ThreeTen-BackportでJava 6および7にバックポートされています。
  • アンドロイド
    • それ以降のバージョンのAndroidには、java.timeクラスの実装がバンドルされています。
    • 以前のAndroid(<26)では、ThreeTenABPプロジェクトはThreeTen-Backport(上記)を採用しています。ThreeTenABPの使用方法…を参照してください。

ThreeTen-エクストラプロジェクトでは、追加のクラスでjava.timeを拡張します。このプロジェクトは、java.timeに将来追加される可能性があることを証明する場です。あなたはここにいくつかの有用なクラスのような見つけることがIntervalYearWeekYearQuarter、および多くを


これは、他のオプションよりもはるかに優れた改善です(これもはるかに新しく、新しいメソッドを利用しています)。あなたがこの問題に今アクセスしているなら、これが進むべき道です。
Shourya Bansal


5

addDaysEliによって提案されたように自分で作成するのではなく、Apacheから使用DateUtilsしたいと思います。これは、プロジェクトで複数の場所で使用する必要がある場合に特に便利です。

APIは言う:

addDays(Date date, int amount)

新しいオブジェクトを返す日付に日数を追加します。

新しいDateオブジェクトを返し、以前のオブジェクト自体には変更を加えないことに注意してください。


2

以下で簡単にできます

Calendar calendar = Calendar.getInstance();
        // from current time
        long curTimeInMills = new Date().getTime();
        long timeInMills = curTimeInMills - 5 * (24*60*60*1000);    // `enter code here`subtract like 5 days
        calendar.setTimeInMillis(timeInMills);
        System.out.println(calendar.getTime());

        // from specific time like (08 05 2015)
        calendar.set(Calendar.DAY_OF_MONTH, 8);
        calendar.set(Calendar.MONTH, (5-1));
        calendar.set(Calendar.YEAR, 2015);
        timeInMills = calendar.getTimeInMillis() - 5 * (24*60*60*1000);
        calendar.setTimeInMillis(timeInMills);
        System.out.println(calendar.getTime());

この回答は、java.timeクラスに取って代わられ、現在はレガシーになっている恐ろしい古い日時クラスを使用しており、不適切なアドバイスです。また、このコードは、タイムゾーンの重要な問題を無視し、単純に24時間と想定しています。別の問題は、日付時刻クラスを使用して日付のみの問題を解決することです。使用する方LocalDateがはるかに簡単で適切です。
バジルブルク2017

1

誰かがJoda Timeをすすめました-私はこのCalendarDateクラス を使用していますhttp://calendardate.sourceforge.net

これはJoda Timeとはやや競合するプロジェクトですが、たった2つのクラスでより基本的です。プロジェクトよりも大きなパッケージを使用したくなかったので、非常に便利で、私が必要とするものに最適です。Javaの対応するものとは異なり、その最小単位は日ですので、実際には日付です(ミリ秒などに下げていません)。日付を作成したら、減算するのはmyDay.addDays(-5)のようなもので、5日間戻ります。曜日などを見つけるために使用できます。もう一つの例:

CalendarDate someDay = new CalendarDate(2011, 10, 27);
CalendarDate someLaterDay = today.addDays(77);

そして:

//print 4 previous days of the week and today
String dayLabel = "";
CalendarDate today = new CalendarDate(TimeZone.getDefault());
CalendarDateFormat cdf = new CalendarDateFormat("EEE");//day of the week like "Mon"
CalendarDate currDay = today.addDays(-4);
while(!currDay.isAfter(today)) {
    dayLabel = cdf.format(currDay);
    if (currDay.equals(today))
        dayLabel = "Today";//print "Today" instead of the weekday name
    System.out.println(dayLabel);
    currDay = currDay.addDays(1);//go to next day
}

1

時間単位(月、日、時間、分、秒など)の減算または加算を実行するためのクリーンで優れた方法は、java.time.Instantクラスを使用して実現できると思います。

現在時刻から5日を減算し、結果を日付として取得する例:

new Date(Instant.now().minus(5, ChronoUnit.DAYS).toEpochMilli());

1時間を減算して15分を加算する別の例:

Date.from(Instant.now().minus(Duration.ofHours(1)).plus(Duration.ofMinutes(15)));

より高い精度が必要な場合、インスタンスはナノ秒まで測定します。ナノ秒部分を操作する方法:

minusNano()
plusNano()
getNano()

また、日付はインスタントほど正確ではありません。


1
または、好みによっては少し短くなります:Date.from(Instant.now().minus(5, ChronoUnit.DAYS))
Ole VV

1
いいね!あなたが正しいです。これを実際に使用するように答えを実際に更新し、java.time.Durationクラスの使用法も示します。この場合も非常に強力です。
Yordan Boev

0

イーライコートライトの2番目の解決策は間違っています。

Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.DATE, -days);
date.setTime(c.getTime().getTime());

2
Eliのソリューションでの関数の名前はaddDaysです。彼の解決策は正しいです。日付から日数を減算する場合は、に負の値を渡しますdays
Thomas Upton

まあ、それは、プログラマーが関数を作成するときに指定しなければならないことですよね?:P
user178973 2010年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.