CodeGym /Java Blog /ランダム /時間を迷わないようにする方法: DateTime と Calendar
John Squirrels
レベル 41
San Francisco

時間を迷わないようにする方法: DateTime と Calendar

ランダム グループに公開済み
やあ!今日は、これまでに見たことのない新しいデータ型、つまり日付の取り扱いを開始します。 時間に迷わない方法: 日時とカレンダー - 1日付とは何かを説明する必要はないと思います。:) 原理的には、現在の日付と時刻を通常の Java String に格納できます。

public class Main {
   public static void main(String[] args) {

       String date = "June 11, 2018";
       System.out.println(date);
   }
}
しかし、このアプローチには多くの欠点があります。このStringクラスはテキストを操作するように設計されており、そのメソッドはこのタスクに適しています。何らかの方法で日付を操作する必要がある場合 (たとえば、2 時間を追加する) は、Stringあまりうまく機能しません。または、プログラムがコンパイルされたときに現在の日付と時刻を表示したい場合。Stringここでも役に立ちません。コードを書いて実行するまでに時刻は変わっており、コンソールには間違った情報が表示されます。Java の作成者が日付と時刻を扱うためのクラスをいくつか提供したのはこのためです。そのうちの 1 つ目は、java.util.Date

日付クラス

別の Java パッケージにそのクラスがあるため、完全名を指定しましたjava.sql.Date。混同しないでください。このシステムについて最初に知っておく必要があるのは、日付が 1970 年 1 月 1 日から経過したミリ秒数として保存されるということです。この時刻システムには、「 Unix-time」という独自の名前もあります。かなり興味深いアプローチです。そう思いませんか?:) 2 番目に覚えておくべきことは、Dateデフォルトのコンストラクターを使用してオブジェクトを作成した場合、結果はオブジェクトが作成された時点の現在の日付と時刻を表します。として表される日付はStringそのようなタスクに苦労するだろうと述べたことを覚えていますか? クラスDateはそれを簡単に処理します。

public class Main {
   public static void main(String[] args) {

       Date date = new Date();
       System.out.println(date);
   }
}
このコードを数回実行すると、時間が繰り返し変化することがわかります。:) これが可能になるのは、時間がミリ秒として保存されているためです。ミリ秒は非常に小さな時間単位であるため、結果は非常に正確です。別のクラスDateのコンストラクター: 1970 年 1 月 1 日の 00:00 から必要な日付までの正確なミリ秒数を渡すと、対応する日付オブジェクトが作成されます。

public class Main {
   public static void main(String[] args) {

       Date date = new Date(1212121212121L);
       System.out.println(date);
   }
}
コンソール出力: Fri May 30 04:20:12 GMT 2008 2008 年 5 月 30 日を取得します。「Fri」は曜日 (金曜日、当然です) を示し、GMT はタイムゾーン (グリニッジ標準時) です。long通常、ミリ秒数は に収まらないため、ミリ秒は sとして渡されますint。それでは、日付を使用してどのような操作を実行する必要があるでしょうか? もちろん、最も明白なのは比較です。ある日付が別の日付の前に来るか後ろに来るかを判断します。これはいくつかの方法で実行できます。たとえば、Date.getTime()1970 年 1 月 1 日の午前 0 時から経過したミリ秒数を返すメソッドを呼び出すことができます。2 つの Date オブジェクトに対してこのメ​​ソッドを呼び出して、結果を比較するだけです。

public class Main {
   public static void main(String[] args) {

       Date date1 = new Date();

       Date date2 = new Date();

       System.out.println((date1.getTime() > date2.getTime())?
               "date1 is later than date2" : "date1 is earlier than date2");
   }
}
出力: date1 は date2 より前です。 ただし、より便利な方法もあります。つまり、Date クラスによって提供される特別なメソッドを使用することですbefore():after()およびequals()。それらはすべてブール値を返します。このbefore()メソッドは、日付が引数として渡された日付よりも前かどうかをチェックします。

public class Main {
   public static void main(String[] args) throws InterruptedException {

       Date date1 = new Date();

       Thread.sleep(2000);// Suspend the program for 2 seconds
       Date date2 = new Date();

       System.out.println(date1.before(date2));
   }
}
コンソール出力: true 同様に、このafter()メソッドは、日付が引数として渡された日付よりも遅いかどうかを確認します。

public class Main {
   public static void main(String[] args) throws InterruptedException {

       Date date1 = new Date();

       Thread.sleep(2000);// Suspend the program for 2 seconds
       Date date2 = new Date();

       System.out.println(date1.after(date2));
   }
}
コンソール出力: false この例では、2 秒間「プログラムをスリープ状態」にしているので、2 つの日付が異なることが保証されます。date1高速なコンピュータでは、と の作成間の時間がdate21 ミリ秒未満になる可能性があり、その場合、before()と の両方がafter()false を返します。ただし、この場合、equals()メソッドは true を返します。結局、日付ごとに 1970 年 1 月 1 日の 00:00 からのミリ秒数を比較します。オブジェクトは、ミリ秒に一致する場合にのみ等しいとみなされます。

public static void main(String[] args) {

   Date date1 = new Date();
   Date date2 = new Date();

   System.out.println(date1.getTime());
   System.out.println(date2.getTime());

   System.out.println(date1.equals(date2));
}
ここでもう 1 つ注意する必要があります。Oracle のDateWeb サイトでこのクラスのドキュメントを開くと、そのメソッドとコンストラクターの多くが非推奨(つまり、使用が推奨されない)としてマークされていることがわかります。Java の作成者は、非推奨になったクラスの部分について次のように述べています。
「@Deprecated という注釈が付けられたプログラム要素は、通常、危険であるか、より良い代替手段があるため、プログラマが使用することはお勧めできません。」
これは、これらの方法がまったく使用できないという意味ではありません。IDE で非推奨のメソッドを使用してコードを実行しようとすると、ほとんどの場合機能します。たとえば、Date.getHours()オブジェクトに関連付けられた時間数を返す非推奨のメソッドについて考えてみましょうDate

public static void main(String[] args) {

   Date date1 = new Date();

   System.out.println(date1.getHours());
}
コードを 14:21 (午後 2 時 21 分) から開始すると、数字 14 が表示されます。ご覧のとおり、非推奨のメソッドには取り消し線が引かれていますが、まだ機能します。これらのメソッドは、それらを使用する既存のコードの巨大な本体を壊さないようにするために削除されません。言い換えれば、これらのメソッドは「壊れ」たり「削除」されたりすることはありません。もっと便利な代替手段があるため、これらの使用は推奨されません。ちなみに、ドキュメントではこの代替案について具体的に言及しています。
時間を迷わない方法: 日時とカレンダー - 2
クラスのメソッドのほとんどは、Date改良および拡張されたCalendarクラスに移動されました。次にそのクラスについて説明します。:)

カレンダークラス

JDK 1.1 では、新しいクラスが導入されましたCalendar。これにより、Java での日付の操作が以前よりもいくらか簡単になりました。Calendarここで扱うクラスの唯一の実装はGregorianCalendarクラスです。世界のほとんどの国で採用されているグレゴリオ暦を採用しています。その主な利点は、より便利な形式で日付を操作できることです。たとえば、次のことが可能です。
  • 現在の日付に月または日を追加します
  • その年がうるう年かどうかを確認します。
  • 日付の個々のコンポーネントを返します (たとえば、日付全体から月番号を抽出します)。
  • また、非常に便利な定数システムも含まれています (その多くは以下で説明します)。
このクラスのもう 1 つの重要な拡張機能は、 Calendar.ERACalendar定数です。西暦より前の日付 (BC - 紀元前) または西暦 (AD - Anno Domini) の日付を指定できます。これらすべてを例を挙げて見てみましょう。2017 年 1 月 25 日の日付を持つオブジェクト を作成しましょう。calendar

public static void main(String[] args) {

  Calendar calendar = new GregorianCalendar(2017, 0 , 25);
}
Calendarクラス (さらにDate言えばクラス)では、月は 0 から始まるため、2 番目の引数として数値 0 を渡します。クラスを操作するときはCalendar、これは単なるカレンダーであり、個々の日付ではないことを理解することが重要です。 時間を迷わない方法: 日時とカレンダー - 3 日付は、特定の時間間隔を示す単なる数字です。カレンダーは、日付を使用してさまざまな操作を実行できるシステム全体です。:) これは、オブジェクトを表示しようとするとよくわかりますCalendar。 出力: java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="ヨーロッパ/ロンドン",offset=0,dstSavings=0,useDaylight= false,transitions=79,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=1,ERA=?,YEAR=2017,MONTH=0,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_MONTH=25,DAY_OF_YEAR=?,DAY_OF_WEEK=? ,DAY_OF_WEEK_IN_MONTH=?,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?] どれだけの情報が得られるかを確認してください 。カレンダーには、通常の日付にはない多数のプロパティがあり、それらがすべて表示されます (これがtoString()内でのメソッドの動作方法Calendar)。カレンダー、つまりオブジェクトから単純な日付を取得する必要があるだけの場合はDateCalendar.getTime()メソッド (この名前はあまり論理的ではありませんが、何ができるでしょうか?):

public static void main(String[] args) {

   Calendar calendar = new GregorianCalendar(2017, 0 , 25);
   Date date = calendar.getTime();
   System.out.println(date);
}
出力: Wed Jan 25 00:00:00 GMT 2017 ここで、カレンダーを通常の日付に「縮小」しました。さらに進んでみましょう。月を数字で指定するだけでなく、Calendarクラスの定数フィールド値を使用することもできます。Calendarこれらの定数は、変更できない事前設定値を持つクラスの静的フィールドです。これらを使用するとコードの可読性が向上するため、これは実際にはさらに優れたオプションです。

public static void main(String[] args) {
   GregorianCalendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
}
Calendar.JANUARY は、年の月を表す定数の 1 つです。これらの名前付き定数を使用すると、たとえば、数字の 3 が 3 月 (私たちが好んで呼ぶ 3 月) ではなく、4 月を意味することを誰も忘れることはありません。Calendar.APRILと書くだけで完了です。:) すべてのカレンダー フィールド (数値、月、分、秒など) は、 メソッドを使用して個別に指定できますset()。このメソッドは、Calendarクラスにフィールドごとに定数があり、結果のコードが非常に読みやすいため、非常に便利です。 最後の例では、日付を作成しましたが、時刻は設定しませんでした。時間を19:42:12に設定しましょう

public static void main(String[] args) {
   Calendar calendar = new GregorianCalendar();
   calendar.set(Calendar.YEAR, 2017);
   calendar.set(Calendar.MONTH, 0);
   calendar.set(Calendar.DAY_OF_MONTH, 25);
   calendar.set(Calendar.HOUR_OF_DAY, 19);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   System.out.println(calendar.getTime());
}
出力: Wed Jan 25 19:42:12 GMT 2017メソッド を呼び出しset()、定数 (変更するフィールドに応じて) とフィールドの新しい値を渡します。set()このメソッドは、1 つのフィールドだけでなく、多くのフィールドの値を設定する方法を知っている一種の「スーパーセッター」であることがわかります。:) このCalendarクラスは、add()値を加算および減算するメソッドを使用します。変更するフィールドと数値 (現在の値に正確に加算/減算する量) を渡します。たとえば、作成した日付の 2 か月前の日付を取得してみましょう。

public static void main(String[] args) {
   Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 19);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   calendar.add(Calendar.MONTH, -2); // To subtract, pass a negative number
   System.out.println(calendar.getTime());
}
出力: Fri Nov 25 19:42:12 GMT 2016 とても良いです! 日付は2か月前にわかりました。これにより、月が変わるだけではなく、年も 2017 年から 2016 年に変わりました。もちろん、日付を変換するときに、現在の年が自動的に計算され、手動で追跡する必要はありません。ただし、何らかの理由でこの動作を無効にする必要がある場合は、無効にすることができます。このメソッドは、残りの値に影響を与えることなく、roll()値を加算および減算できます。たとえば、次のようになります。

public static void main(String[] args) {
   Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 10);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   calendar.roll(Calendar.MONTH, -2);
   System.out.println(calendar.getTime());
}
前の例とまったく同じことを行いました。つまり、現在の日付から 2 か月を取得しました。しかし、今度はコードの動作が異なります。月は 1 月から 11 月に変更されましたが、年は変更されず、2017 年です。出力: Sat Nov 25 10:42:12 GMT 2017 順調に進んでいます。上で述べたように、すべてのフィールドを個別に取得できますCalendar。これを次のメソッドで行いますget()

public static void main(String[] args) {
   GregorianCalendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 10);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   System.out.println("Year: " + calendar.get(Calendar.YEAR));
   System.out.println("Month: " + calendar.get(Calendar.MONTH));
   System.out.println("Week in the month: " + calendar.get(Calendar.WEEK_OF_MONTH));// Week in this month?

   System.out.println("Day: " + calendar.get(Calendar.DAY_OF_MONTH));

   System.out.println("Hours: " + calendar.get(Calendar.HOUR));
   System.out.println("Minutes: " + calendar.get(Calendar.MINUTE));
   System.out.println("Seconds: " + calendar.get(Calendar.SECOND));
   System.out.println("Milliseconds: " + calendar.get(Calendar.MILLISECOND));

}
出力: 年: 2017 月: 0 月の週: 5 日: 25 時間: 10 分: 42 秒: 12 ミリ秒: 0 したがって、クラスの「スーパーセッター」に加えてCalendar、「スーパーゲッター」もあります。 」。:) もちろん、このクラスのもう 1 つの興味深い側面は、時代を扱うことです。「BC」日付を作成するには、 Calendar.ERAフィールドを使用する必要があります。たとえば、ハンニバルがローマ軍を破ったカンナエの戦いの日付を作成してみましょう。これは紀元前 216 年 8 月 2 日に起こりました。

public static void main(String[] args) {
   GregorianCalendar cannae = new GregorianCalendar(216, Calendar.AUGUST, 2);
   cannae.set(Calendar.ERA, GregorianCalendar.BC);

   DateFormat df = new SimpleDateFormat("MMM dd, yyy GG");
   System.out.println(df.format(cannae.getTime()));
}
ここでは、クラスを使用してSimpleDateFormat、理解しやすい形式で日付を出力しました (「GG」という文字は、元号を表示したいことを示しています)。出力: 紀元前 216 年 8 月 2 日。 このCalendarクラスにはさらに多くのメソッドと定数があります。これらについてはドキュメントを参照してください。この日付形式Sat Nov 25 10:42:12 GMT 2017が気に入らない場合は 、 を使用してSimpleDateFormat簡単に希望どおりの日付形式にすることができます。

public static void main(String[] args) {

   SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE, MMMM d, yyyy");
   Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 10);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   calendar.roll(Calendar.MONTH, -2);
   System.out.println(dateFormat.format(calendar.getTime()));
}
出力: 2017 年 11 月 25 日 (土) そのほうがずっと良いですよね。:)
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION