Count number of days based on custom time unit

AMagic :

I have a class with number and timeUnit

public static class Time {
    private int number;
    private Unit unit;
}

TimeUnit is an enum

public enum Unit {
    days,
    months,
    years;
}

So the possible values of Time are

[0-Integer.MAX] DAYS
[0-Integer.MAX] MONTHS
[0-Integer.MAX] YEARS

I want to minus the Time from Today's date but now sure how I can achieve it.

Here is an example,

if TimePeriod is 30 DAYS, then resultedDate = Instant.now() - 30 DAYS.

if TimePeriod is 15 MONTHS, then resultedDate = Instant.now() - 450 DAYS

if TimePeriod is 2 YEARS, then resultedDate = Instant.now() - 730 DAYS

Ole V.V. :

I realized that I need to consider 12 months not as 360 days and also calculate leap years. Any ideas for that?

First you need to decide on a time zone for that. Why? Say you were running this code at (UTC) 2019-02-28T23:00:00Z and you want to subtract 1 month. At this point in time it’s February 28 in Mexico City, so the result should fall on January 28. By contrast in Shanghai it’s already March 1, so the result should fall on February 1. The difference is 3 days (72 hours).

Once you’ve decided on a time zone, it’s easiest to use ZonedDateTime. You can always convert to Instant after subtracting, that’s straightforward too.

For example:

    ZoneId zone = ZoneId.of("Asia/Ashkhabad");
    Map<Unit, ChronoUnit> units = Map.of(Unit.days, ChronoUnit.DAYS,
            Unit.months, ChronoUnit.MONTHS, Unit.years, ChronoUnit.YEARS);

    Time timeToSubtract = new Time(15, Unit.months);

    Instant result = ZonedDateTime.now(zone)
            .minus(timeToSubtract.getNumber(), units.get(timeToSubtract.getUnit()))
            .toInstant();
    System.out.println("15 months ago was " + result);

When running just now (2019-05-08T07:06:45Z) I got this output:

15 months ago was 2018-02-08T07:06:45.353746Z

The ZonedDateTime.minus method that I am using understands ChronoUnit but of course not your Unit enum, so since you get the latter, we need to translate (or your enum would have to implement TemporalUnit, but that would be overkill). I am using a map for the translation. I am initializing the map the Java 9 way. If you are still on Java 8, I trust you to fill it some other way.

In my code I have assumed that your Time class has usual constructor and getters.

ZonedDateTime also takes into account that a day is not always 24 hours. For example, when in spring summer time (DST) begins and the clocks are turned forward, the day is only 23 hours. And then 25 hours the day the clocks are turned back in the fall.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=116275&siteId=1