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
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.