0

私はいくつかのレガシーコードで作業しており、いくつかの値を繰り返し処理しています。レガシーコードは、sql.timestamp 値を使用して新しい日の始まりをチェックしています:

public static final long MILLIS_PER_SECOND = 1000;
public static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
public static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;
public static final long MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR;

 if (entry.getPeriodEnd().getTime() % TimestampUtils.MILLIS_PER_DAY == 0 || i >= throughputEntries.size()) {

       ...
}

結果はnever0なので、ifwhenにのみ入りますi >= throughputEntries.size()

彼がどのように結果を得ていたのか、私には理解できません0。おそらく彼のデータは異なっていて、常に特定の期間で終了し、0

日付を確認するためにコードを書き直すこともできますが、彼が自分のコードでそれをどのように達成したか知りたいです。

私が提供したコードでこれを解決できるかどうかはわかりませんが、何か不足している可能性があります...

編集

@t0r0Xと@Leoのおかげで、最終的にこれについて頭を悩ませました

次のようにJoda-Timeを使用するようにコードを変更しました。

 LocalDate newDay = null;
 int count = 0;


public void calcAvg(){

    DateTimeZone zone = DateTimeZone.getDefault();
    LocalDate throughtputDate = entry.getPeriodEnd().toDateTime(zone).toLocalDate();

    if ( this.newDay(throughtputDate) || i >= throughputEntries.size()) {

       ...
    }

}


public boolean newDay(LocalDate date){

    boolean go = false;
    if(count !=0){
        if(date.isAfter(newDay)){

            newDay = date;
            go = true;
        }
    }
    else{
        newDay = date;
        count++;
    }

    return go;
}

おそらく、私が書いた方法よりも新しい日付を確認するためのよりクリーンな方法ですが、時間は誰も待っていません。

4

2 に答える 2

3

元のコードの作成者は、おそらく合成の「ラウンド」データを使用した可能性があります。たぶん(最近では非推奨になっている)java.sql.Timestampコンストラクターを使用しています...

new Timestamp(116, 1, 25, 0, 0, 0, 0)

または、(これも非推奨の)Date コンストラクターを使用することもできます...

new Timestamp(new Date(116, 1, 25).getTime())

または、「2016-01-25」などのテストデータを解析した可能性があります...

ほら、ミリじゃないよ!;-)

とにかく、「新しい日」を確認する方法は、それをどのように定義するかによって異なります。通常、以前に処理されたエントリのように、基準日が必要です。

アップデート:

コードを4回目に見るとentry.getPeriodEnd().getTime()、エントリは期間のように見えます...したがって、getPeriodBegin()方法が必要です...必要なチェックは、期間の終了が期間の開始日とは別の日であるかどうかを確認することだと思います...私は正しいですか?

汚いコード (非推奨のメソッド):

Timestamp begin = entry.getPeriodBegin()
Timestamp end = entry.getPeriodEnd()
if (begin.getYear() != end.getYear() || begin.getMonth() != end.getMonth() || begin.getDay() != end.getDay() ....) 

きれいなコード:私の推奨事項: java.util.Calendar (Stackoverflow の提案)
から始めないでください。Apache Commons Lang の DateUtils を使用するか(ここでも Stackoverflow で提案されています。コメントは関連しています)、または私のお気に入りは、JodaTimeを取得して心配をやめてください (Stackoverflow でも提案されています。コメントは関連しています)。個人的には、JodaTime にはいつも満足しています。

PS

忘れないでください(質問に対する@Leoのコメントに感謝します。私はまだJava 6-7の世界で働いています:-/ ...):Java 8以降を使用している場合は、新しいjava.timeクラス。

于 2016-01-25T19:28:45.993 に答える
1

t0r0Xによる回答は正しいですが、古いクラスを使用しています。

また、通常、java.sql.* クラスを使用してビジネス ロジックを実行するべきではありません。これらは、データベースに出入りするデータ転送を目的としていますが、それ以上のものではありません。すぐに java.sql.Timestamp/.Date/.Time を java.time 型に変換します。ビジネス ロジックを java.time 型で実行します。Java.time を直接処理するように JDBC ドライバーが更新された後、いつの日か java.sql 型が消えてなくなることを願っています。

質問とコメントは明確ではありません。しかし、日付ごとに数字を累積することに関係しているように見えるので、突き刺します。

java.time

Java 8 以降には、優れたjava.timeフレームワークが付属しています。チュートリアルを参照してください。これらの新しいクラスは、java.util.Date/.Calendar の古い面倒なクラスに取って代わります。

これらの新しいクラスの中にはLocalDate、時刻もタイム ゾーンもない日付のみの値があります。はjava.sql.Timestamp、日付のみではなく日時の値です。しかし、 UTCjava.time.Instantのタイムライン上の瞬間に変換できます。次に、タイムゾーン ( ) を適用して を取得します。そこから を抽出できます。これは、数値の合計を累積するための a のキーとして必要なものです。ZoneIdZonedDateTimeLocalDateLocalDateMap

Instant instant = myJavaSqlTimestamp.toInstant();
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
LocalDate localDate = zdt.toLocalDate();

ここではタイムゾーンが重要であることに注意してください。はタイム ゾーンをLocalDate保持しませんが、日付はタイム ゾーンのコンテキストでのみ意味を持ちます。日付は、特定の時点で世界中で同じではありません。指定しない場合、JVM の現在のデフォルトのタイム ゾーンが適用されます。このページの他のコードは、現在のデフォルトを明示的に要求しました。この問題ではデフォルトを使用しないことを強くお勧めします。JVM の現在のデフォルト タイム ゾーンは、アプリの実行前、さらにはアプリの実行中にいつでも変更できます。日付ごとに数値を合計する場合、ビジネス ロジックでは、その日付の意味のためにタイム ゾーンを考慮する必要があります。そのタイム ゾーンを明示的に指定します。ここでは勝手に選んでいAmerica/Montrealます。

Map以前に、LocalDate の を収集された数値の合計にインスタンス化していたでしょう。BigIntegerこのデモでは、数値型としてを扱っていると仮定します。

Map< LocalDate , BigInteger ) map = new HashMap<>();

LocalDate遭遇した日付値ごとにその Map にエントリを追加します。myNumberJDBC を介してデータベースから取得した BigInteger があると仮定します。

BigInteger oldTotalForDate = map.get( localDate );
BigInteger newTotalForDate = ( null == oldTotalForDate ) ? myNumber : oldTotalForDate.add( myNumber) ;
if ( null == newTotalForDate ) {  // If we failed to get new sum.
    // TODO: Handle error condition. Perhaps: map.remove(key);
} else {  // Else normal, we have a new total. Store it in map.
    map.put( localDate , newTotalForDate );  // Replaces any old value.
}

Map::merge上記のコードは、Java 8 以降の新しい Lambda 構文機能を使用する新しいメソッドを使用することで短縮される場合があります。

于 2016-01-27T01:34:56.057 に答える