2017-11-10 12 views
0

現在の時間に数年を追加しようとしています。私のコードは次のようになります。java.time.Instant.plus(long amountToAdd、TemporalUnit unit)サポートされていないユニット

// ten yeas ago 
int backYears = 10; 
Instant instant = ChronoUnit.YEARS.addTo(Instant.now(), -backYears); 

しかし、私は例外が発生しました:あなたはMONTHSYEARSを見ることができるように

@Override 
public Instant plus(long amountToAdd, TemporalUnit unit) { 
    if (unit instanceof ChronoUnit) { 
     switch ((ChronoUnit) unit) { 
      case NANOS: return plusNanos(amountToAdd); 
      case MICROS: return plus(amountToAdd/1000_000, (amountToAdd % 1000_000) * 1000); 
      case MILLIS: return plusMillis(amountToAdd); 
      case SECONDS: return plusSeconds(amountToAdd); 
      case MINUTES: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_MINUTE)); 
      case HOURS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_HOUR)); 
      case HALF_DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY/2)); 
      case DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY)); 
     } 
     throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit); 
    } 
    return unit.addTo(this, amountToAdd); 
} 

:私は以下を参照してください方法Instant.plusを開け

java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Years 
at java.time.Instant.plus(Instant.java:862) 

サポートされていません。しかし、なぜ?古いjava.util.Calendarで は、私は簡単にそれを行うことができます。

Calendar c = Calendar.getInstance(); 
    c.setTime(date); 
    c.add(Calendar.YEAR, amount); 
    return c.getTime(); 

を私が推測するものを一つだけの理由は、私たちが何日、月と年のため、うるう日の2月29日 でもするのか分からないということです正直言って、leap secondもあります。 これはバグだと思っており、すべてChronoUnitがサポートされているはずです。 唯一の問題は、閏年と閏年を考慮に入れなければならないことです。 私の必要に応じて、その月は30日と365日と仮定するだけで大​​丈夫です。 Calendar.roll()のようなものを作る必要はありませんが、これも私を満足させることができます。

+0

私はクラスをデザインしていないので、私は確かに言えません。私はナノ秒から数日までのユニットを瞬間的に秒とナノに変換することができると考えています(閏秒を無視するのでほとんどのコンピュータで無視されるため)。 'ZonedDateTime'、' OffsetDateTime'、 'LocalDateTime'のようなクラスは、月と年の扱い方を知っています。 –

答えて

0

何か試してみましょう。私はZonedDateTimeとして瞬間をとり、異なる時間帯で10年を引いています。

OffsetDateTime origin = OffsetDateTime.of(2018, 3, 1, 0, 0, 0, 0, ZoneOffset.UTC); 
    Instant originInstant = origin.toInstant(); 
    Instant tenYearsBackKyiv = origin.atZoneSameInstant(ZoneId.of("Europe/Kiev")) 
      .minusYears(10) 
      .toInstant(); 
    long hoursSubtractedKyiv = ChronoUnit.HOURS.between(tenYearsBackKyiv, originInstant); 
    System.out.println("Hours subtracted in Київ: " + hoursSubtractedKyiv); 
    Instant tenYearsBackSaoPaulo = origin.atZoneSameInstant(ZoneId.of("America/Sao_Paulo")) 
      .minusYears(10) 
      .toInstant(); 
    long hoursSubtractedSaoPaulo = ChronoUnit.HOURS.between(tenYearsBackSaoPaulo, originInstant); 
    System.out.println("Hours subtracted in São Paulo: " + hoursSubtractedSaoPaulo); 

出力は、次のとおりです。あなたが見ることができるように

Hours subtracted in Київ: 87648 
Hours subtracted in São Paulo: 87672 

は、24時間以上(1日以上)Київ(キエフ、キエフ)に比べサンパウロに差し引かれます。 3月1日から2月29日まで、閏年で3回、Київで2回しか通過しないので、既にそれがわかっているかもしれません。

古くて古くなったCalendarクラスには常にタイムゾーンがありますので、どのタイムゾーンで年数を引いたのか分かりました(別のことは、結果が不明な場合でも結果を教えてください欲しい)。現代のクラスZonedDateTimeOffsetDateTimeおよびLocalDateTimeは同じことをすることができます。だから、それらを使用してください。 Instantは概念的にタイムゾーンを持たないため、タイムゾーンに依存する操作を拒否します(UTCを使用して実装されていることがわかりますが、これはインターフェイスの仕様の一部ではなく、無関係な実装の詳細と見なす必要があります)クラスに)。

古いクラスと現代クラスのどちらも、閏年を考慮していないため、正しい場合は、Instantで日、時間、分を加算したり減算することができます。

関連する問題