java.time.Instant.plus(long amountToAdd,TemporalUnit单位)不支持的单位 [英] java.time.Instant.plus(long amountToAdd, TemporalUnit unit) Unsupported unit

查看:138
本文介绍了java.time.Instant.plus(long amountToAdd,TemporalUnit单位)不支持的单位的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将当前时间增加几年.我的代码如下:

I trying to add few years to current time. My code looks like:

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

但是我有一个例外:

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

当我打开方法Instant.plus时,我看到以下内容:

When I opened the method Instant.plus I see the following:

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

如您所见,不支持MONTHSYEARS.但为什么? 使用旧的java.util.Calendar,我可以轻松做到这一点:

As you can see MONTHS and YEARS are unsupported. But why? With an old java.util.Calendar I can do that easily:

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

我猜的唯一一个原因是,由于2月29日leap日,我们不知道一个月和一年中有多少天. 但老实说,我们还有一个跃居第二. 因此,我认为这是一个错误,所有ChronoUnit都应得到支持. 唯一的问题是:我们是否需要考虑leap秒和leap日. 至于我的需求,可以假设该月份为30天,并且是365年. 我不需要制作Calendar.roll()之类的东西,但这也可以使我满意.

The only one reason what I guess is that we don't know how many days in a month and year because of leap day 29 Feb. But to be honest we also have a leap second. Thus I think that this is a bug and all ChronoUnits should be supported. The only one question is: do we need to take in account leap second and leap day. As for my needs it's okay just to assume that month has 30 days and year 365. I don't need to make something like Calendar.roll() but this can satisfy me too.

推荐答案

让我们尝试一下.我以ZonedDateTime表示瞬间,并在不同时区减去10年.

Let’s try something out. I am taking an instant as ZonedDateTime and subtracting 10 years in different time zones.

    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天).您可能已经发现,这是因为我们在years年从3月1日到2月29日经过了三次,而在Київ只经过了两次.

As you can see, 24 hours more (1 day more) is subtracted in São Paulo compared to Київ (Kyiv, Kiev). You may already have figured out that it’s because there we pass from 1 March to 29 February three times in leap years, in Київ only twice.

古老而又过时的Calendar类中始终有一个时区,因此知道在哪个时区中减去年数(另一件事是,即使在不清楚哪个结果的情况下,也很乐意为您提供结果你自找的).现代类ZonedDateTimeOffsetDateTimeLocalDateTime可以做到相同.因此,使用它们. Instant从概念上讲没有时区,因此拒绝执行依赖于时区的操作(我知道它是使用UTC实现的,但是我们应该将其视为不相关的实现细节,而不应将其视为规范的一部分.类的接口).

The old and now outdated Calendar class always had a time zone in it, so knew in which time zone to subtract years (another thing is it was happy to give you a result even in situations where it was unclear which result you wanted). The modern classes ZonedDateTime, OffsetDateTime and LocalDateTime can do the same. So use them. An Instant conceptually doesn’t have a time zone, so refuses to do operations that depend on time zone (I know it’s implemented using UTC, but we should regard this as an irrelevant implementation detail, not as a part of the specification of the interface to the class).

无论是老式的还是现代的类,都没有考虑到跳跃式的变化,而您是对的,因此,Instant只能加上和减去天,小时和分钟.

Neither the old nor the modern classes take leap seoncds into account, and you are right, only therefore can an Instant add and subtract days, hours and minutes.

这篇关于java.time.Instant.plus(long amountToAdd,TemporalUnit单位)不支持的单位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆