私は仕事でいくつかのコードをレビューしていますが、コードが現在の時間に1週間を追加する方法に矛盾があり、一方が他方よりも本当に優先されるべき理由があるかどうか疑問に思いました。
最初はユーティリティメソッドでした:
public static Date addDaysToDate(final Date date, int noOfDays) {
Date newDate = new Date(date.getTime());
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(newDate);
calendar.add(Calendar.DATE, noOfDays);
newDate.setTime(calendar.getTime().getTime());
return newDate;
}
そして2番目は単純なミリ秒演算を使用しました:
long theFuture = System.currentTimeMillis() + (86400 * 7 * 1000);
Date nextWeek = new Date(theFuture);
2番目の方法は明らかに「マジックナンバー」を使用して週を定義しますが、これは定数MILLISECONDS_IN_ONE_WEEK = 86400 * 7 * 1000
に移動できます。それ以外に、これらの方法の1つを他の方法よりも優先する理由はありますか?
基本的に、コード全体で一貫性を保つように変更したいのですが、どれを削除すればよいか完全にはわかりません。したがって、いずれかの方法での引数は役に立ちます。
2つの方法は、夏時間の境界で異なる動作をします。最初の方法は、夏時間のステータスに関係なく、同じ時刻を返し続けます。 2番目の方法は、夏時間が開始および停止するときに、各方向で1時間変化する時間を返します。
私を捕まえた 先日、方法2の使用には十分注意してください。検討する
private static long ONE_YEAR_AS_MILLISECONDS = 365*24*60*60*1000;
これは十分に無害に見えますが、実際には、乗算で整数が使用されるため、期待どおりの結果が得られません。整数を他の整数で乗算すると、数値のオーバーフローが発生し、予期しない結果が発生します。これは、Javaの最大int値が2,147,483,647であるにもかかわらず、1年に31,536,000,000ミリ秒あるためです。私のマシンでは、上記のコードは1,471,228,928を生成しますが、これは明らかに正しくありません。
代わりに、これを行う必要があります。
private static long ONE_YEAR_AS_MILLISECONDS = 365L*24L*60L*60L*1000L;
以下はJava 8、Java 8 rocks !!
public static void main(String[] args) {
LocalDate today = LocalDate.now();
System.out.println("Current date: " + today);
//add 1 week to the current date
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
System.out.println("Next week: " + nextWeek);
}
何よりもまず、JodaTimeに置き換えることをお勧めします。 http://joda-time.sourceforge.net/ これはとても素敵な時間ライブラリです。このページを見て、特定の時点に日または週を追加するのがいかに簡単かを確認してください。 http://joda-time.sourceforge.net/key_period.html これを行うことはできません、互換性のないJVMを備えたモバイルデバイス。バマー。
最初の例は読みやすく、開発者にとっても使いやすいでしょう。また、Javaで日付を操作するために一般的に受け入れられている方法であるCalendarクラスを使用します。それをより良くするのは、それが何をするかについての期待を設定する明確なメソッド名を持っているということです。
したがって、com.DaveJ.util.date.DateUtils.addDaysToDate(final Date date、int noOfDays)を一貫して使用するようにシステムをリファクタリングすると、Calendar、millis、Jodaなど、そのメソッド内で必要なことを実行でき、一貫性が保たれます。アプリケーション内。そのためのいくつかのユニットテストを書くことを忘れないでください!
より一般的であるほど、それはより有用になります。いつも1週間追加する場合は、2番目の方法を選択します。別の追加がある場合は、最初の追加を選択します。必要に応じて、日を数秒、さらにはミリ秒に置き換えます。
1つ目は遅くなるため、パフォーマンスが問題になる場合は2つ目が優れています。
場合によります!うるう秒、DST、およびその他のカレンダーの異常のため、この2つは常に同等であるとは限りません。
ビジネスや日常の使用では、常に最初の方法を使用してください。パフォーマンスはまったく悪くありません。それはあなたのためにそれらのものを処理します。
科学的なニーズのために、多くの場合、単調な時計(ここでは2番目の時計)を使用する必要があります。
日付のみの値については、 javaHelperによる回答 を参照してください。 LocalDate
クラスには、意図的に時刻やタイムゾーンがありません。
ZonedDateTime
日時の値については、 ZonedDateTime
を使用して、夏時間(DST)などの異常を説明するためのタイムゾーンとともに日付と時刻を表します。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( zoneId );
ZonedDateTime weekLater = now.plusWeeks( 1 );
または、任意の日数を追加します。
ZonedDateTime later = now.plusDays( someNumberOfDays );
Java.time フレームワークはJava 8以降に組み込まれています。これらのクラスは、Java.util.Date
、.Calendar
、Java.text.SimpleDateFormat
などの古い厄介な日時クラスに取って代わります。
Joda-Time プロジェクトは、現在 メンテナンスモード であり、Java.timeへの移行をアドバイスします。
詳細については、 Oracleチュートリアル を参照してください。そして、StackOverflowで多くの例と説明を検索してください。
Java.time機能の多くはJava 6&7 in ThreeTen-Backport にバックポートされ、さらに Android in-に適合されます) ThreeTenABP 。
ThreeTen-Extra プロジェクトは、Java.timeを追加のクラスで拡張します。このプロジェクトは、Java.timeに将来追加される可能性のある試験場です。
夏時間の変更が含まれる場合、2つの方法で異なる結果が得られる可能性があります。現在の時刻が23:50で、02:00に時計が03:00にジャンプするとします。ミリ秒単位で7日を追加すると、次の日の00:50になります。 7日を追加しても、結果の時間は23:50になります。
混乱を完全にするために、add(Calendar.WEEK_OF_YEAR, 1)
を試すこともできますが、それがどのように異なるかはわかりません。
モバイルデバイスで使用しているため、最初の方法が推奨されます。その理由は、コードが特定のカレンダー、DST、および秒オーバーラン(うるう秒)などの他の問題から独立している必要があるためです。
GregorianCalendar
への依存を削除し、Calendar.getInstance()
を使用して作成する必要があります。