2017-11-10 15 views
0

Ich versuche einige Jahre zur aktuellen Zeit hinzuzufügen. Mein Code sieht so aus:java.time.Instant.plus (long amountToAdd, Unit TemporalUnit) Nicht unterstützte Einheit

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

Aber ich habe eine Ausnahme:

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

Wenn ich die Methode geöffnet Instant.plus Ich sehe die folgenden:

@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); 
} 

Wie Sie MONTHS und YEARS sehen werden nicht unterstützt. Aber warum? Mit einer alten java.util.Calendar kann ich das einfach tun:

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

Der einzige Grund, was ich denke, ist, dass wir nicht wissen, wie viele Tage in einem Monat und Jahr wegen des Schalttag 29 Februar Aber Seien Sie ehrlich, wir haben auch eine leap second. Also ich denke das ist ein Bug und alle ChronoUnit s sollten unterstützt werden. Die einzige Frage ist: müssen wir Schaltsekunde und Schalttag berücksichtigen. Für meine Bedürfnisse ist es okay, nur davon auszugehen, dass der Monat 30 Tage und Jahr 365 hat. Ich muss nicht so etwas wie Calendar.roll() machen, aber das kann mich auch befriedigen.

+0

Ich habe die Klasse nicht entworfen, also kann ich nicht sicher sagen. Ich denke, dass die Einheiten von Nanos bis zu Tagen eindeutig in Sekunden und Nanos umgewandelt werden können (wobei Schaltsekunden ignoriert werden, weil fast alle Computer sie ignorieren) und daher unterstützt werden. Klassen wie 'ZonedDateTime',' OffsetDateTime' und 'LocalDateTime' wissen, wie man mit Monaten und Jahren umgeht, also verwende sie zum Hinzufügen solcher Einheiten. –

Antwort

0

Lassen Sie uns etwas ausprobieren. Ich nehme einen Augenblick als ZonedDateTime und subtrahiere 10 Jahre in verschiedenen Zeitzonen.

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); 

Die Ausgabe lautet:

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

Wie Sie sehen können, weitere 24 Stunden (1 Tag mehr) subtrahiert wird in São Paulo im Vergleich zu Київ (Kiew, Kiew). Sie haben vielleicht schon herausgefunden, dass es daran liegt, dass wir vom 1. März bis zum 29. Februar dreimal in Schaltjahren, in Kiew nur zweimal, durchgehen.

Der alte und jetzt Calendar Klasse hatte immer eine Zeitzone in sie veraltet, in so wusste Zone, die Zeit Jahre zu subtrahieren (eine andere Sache ist es glücklich, Ihnen ein Ergebnis auch in Situationen zu geben, wo es unklar war, die Sie führen wollte). Die modernen Klassen ZonedDateTime, OffsetDateTime und LocalDateTime können das gleiche tun. Also benutz sie. Ein Instant hat konzeptionell keine Zeitzone, also weigert er sich, Operationen auszuführen, die von der Zeitzone abhängen (ich weiß, dass es mit UTC implementiert ist, aber wir sollten dies als irrelevantes Implementierungsdetail betrachten, nicht als Teil der Spezifikation der Schnittstelle zur Klasse).

Weder die alten noch die modernen Klassen berücksichtigen Sprungweiten, und Sie haben Recht, nur deshalb können Sie eine Instant Tage, Stunden und Minuten addieren und subtrahieren.

Verwandte Themen