
de.galan.commons.time.Instants Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of commons Show documentation
Show all versions of commons Show documentation
Additional common functionality for Java developers.
package de.galan.commons.time;
import static org.apache.commons.lang3.StringUtils.*;
import java.time.DayOfWeek;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.TemporalUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import de.galan.commons.logging.Say;
/**
* Construction of time-objects with a fluent interface. Provides a a simple but useful subset for creating, modfing and
* formatting time-based objects. Application-wide time will be setup in ApplicationClock.
* See also https://github.com/galan/commons/blob/master/documentation/Instants.md
*
* @author galan
*/
public class Instants {
/*
TemporalAdjuster
*/
public static final String DATE_FORMAT_LOCAL = "yyyy-MM-dd HH:mm:ss[.SSS]";
public static final String DATE_FORMAT_UTC = "yyyy-MM-dd'T'HH:mm:ss[.SSS]'Z'";
public static final ZoneId ZONE_LOCAL = ZoneId.systemDefault().normalized();
public static final ZoneId ZONE_UTC = ZoneId.of("UTC").normalized();
private static final Map FORMATTERS = new ConcurrentHashMap<>();
private static DateTimeFormatter getFormater(String pattern, String timezone) {
String key = pattern + "//" + timezone;
DateTimeFormatter result = FORMATTERS.get(key);
if (result == null) {
result = DateTimeFormatter.ofPattern(pattern);
if (isNotBlank(timezone)) {
result = result.withZone(ZoneId.of(timezone));
}
FORMATTERS.put(key, result);
}
return result;
}
public static Instant now() {
return Instant.now(ApplicationClock.getClock());
}
public static Instant tomorrow() {
return now().plus(1L, ChronoUnit.DAYS);
}
public static Instant yesterday() {
return now().minus(1L, ChronoUnit.DAYS);
}
public static Date dateNow() {
return Date.from(now());
}
public static Date dateLocal(String text) {
Instant instant = instantLocal(text);
return instant != null ? Date.from(instant) : null;
}
public static Date date(long epochMilli) {
//Date.from(instant(epochMilli))
return new Date(epochMilli);
}
public static Date dateUtc(String text) {
return Date.from(instantUtc(text));
}
/** Creates an Instant, input format is "yyyy-MM-dd HH:mm:ss[.SSS]", system default (local) timezone is used. */
public static Instant instantLocal(String text) {
return instant(text, ZONE_LOCAL);
}
/** Creates an Instant, input format is "yyyy-MM-dd HH:mm:ss[.SSS]", given timezone is used. */
public static Instant instant(String text, ZoneId zone) {
Instant result = null;
try {
LocalDateTime ldt = LocalDateTime.parse(text, getFormater(DATE_FORMAT_LOCAL, null));
ZonedDateTime zdt = ldt.atZone(zone);
result = zdt.toInstant();
}
catch (DateTimeParseException ex) {
Say.warn("Instant not constructable {}", ex, text);
}
return result;
}
/** Creates an Instant, input format is "yyyy-MM-dd'T'HH:mm:ss[.SSS]'Z'", timezone is UTC. */
public static Instant instantUtc(String text) {
Instant result = null;
try {
ZonedDateTime zdt = ZonedDateTime.parse(text, getFormater(DATE_FORMAT_UTC, "UTC"));
//LocalDateTime ldt = LocalDateTime.parse(text, getFormater(DATE_FORMAT_UTC, "UTC"));
result = zdt.toInstant();
}
catch (DateTimeParseException ex) {
Say.warn("Instant not constructable {}", ex, text);
}
return result;
}
/** Creates an Instant from the milliseconds since the epoch. */
public static Instant instant(long epochMilli) {
return Instant.ofEpochMilli(epochMilli);
}
public static InstantBuilder from(Instant instant) {
return new InstantBuilder(instant);
}
public static InstantBuilder from(Date date) {
return new InstantBuilder(date.toInstant());
}
public static DatetimeUnit milli() {
return DatetimeUnit.millis;
}
public static DatetimeUnit millis() {
return DatetimeUnit.millis;
}
public static DatetimeUnit second() {
return DatetimeUnit.seconds;
}
public static DatetimeUnit seconds() {
return DatetimeUnit.seconds;
}
public static DatetimeUnit minute() {
return DatetimeUnit.minutes;
}
public static DatetimeUnit minutes() {
return DatetimeUnit.minutes;
}
public static DatetimeUnit hour() {
return DatetimeUnit.hours;
}
public static DatetimeUnit hours() {
return DatetimeUnit.hours;
}
public static DatetimeUnit day() {
return DatetimeUnit.day;
}
public static DatetimeUnit days() {
return DatetimeUnit.day;
}
public static DatetimeUnit week() {
return DatetimeUnit.week;
}
public static DatetimeUnit weeks() {
return DatetimeUnit.week;
}
public static DatetimeUnit month() {
return DatetimeUnit.month;
}
public static DatetimeUnit months() {
return DatetimeUnit.month;
}
public static DatetimeUnit year() {
return DatetimeUnit.year;
}
public static DatetimeUnit years() {
return DatetimeUnit.year;
}
public static WeekdayUnit monday() {
return WeekdayUnit.monday;
}
public static WeekdayUnit tuesday() {
return WeekdayUnit.tuesday;
}
public static WeekdayUnit wednesday() {
return WeekdayUnit.wednesday;
}
public static WeekdayUnit thursday() {
return WeekdayUnit.thursday;
}
public static WeekdayUnit friday() {
return WeekdayUnit.friday;
}
public static WeekdayUnit saturday() {
return WeekdayUnit.saturday;
}
public static WeekdayUnit sunday() {
return WeekdayUnit.sunday;
}
/** Actual builder class */
public static class InstantBuilder {
private Instant current;
private ZoneId zone = ZONE_UTC;
public InstantBuilder(Instant instant) {
current = instant;
}
public InstantBuilder zone(ZoneId zoneId) {
zone = zoneId == null ? ZONE_UTC : zoneId;
return this;
}
public InstantBuilder with(TemporalAdjuster adjuster) {
current = current.with(adjuster);
return this;
}
public InstantBuilder in(int amount, DatetimeUnit unit) {
if (unit == DatetimeUnit.week || unit == DatetimeUnit.month || unit == DatetimeUnit.year) {
ZonedDateTime zdt = ZonedDateTime.ofInstant(current, zone);
current = zdt.plus(amount, unit.getUnit()).toInstant();
}
else {
current = current.plus(amount, unit.getUnit());
}
return this;
}
public InstantBuilder before(int amount, DatetimeUnit unit) {
if (unit == DatetimeUnit.week || unit == DatetimeUnit.month || unit == DatetimeUnit.year) {
ZonedDateTime zdt = ZonedDateTime.ofInstant(current, zone);
current = zdt.minus(amount, unit.getUnit()).toInstant();
}
else {
current = current.minus(amount, unit.getUnit());
}
return this;
}
public InstantBuilder next(DatetimeUnit unit) {
return truncate(unit).in(1, unit);
}
public InstantBuilder previous(DatetimeUnit unit) {
return truncate(unit).before(1, unit);
}
/** Truncates the time using the defined timezone */
public InstantBuilder truncate(DatetimeUnit unit) {
ZonedDateTime zdt = ZonedDateTime.ofInstant(current, zone);
switch (unit) {
case year:
zdt = zdt.withMonth(1);
case month:
zdt = zdt.withDayOfMonth(1);
case day:
zdt = zdt.withHour(0);
case hours:
zdt = zdt.withMinute(0);
case minutes:
zdt = zdt.withSecond(0);
case seconds:
zdt = zdt.withNano(0);
break;
case millis:
long millis = zdt.getLong(ChronoField.MILLI_OF_SECOND);
zdt = zdt.withNano((int)(millis * 1_000_000L));
}
current = zdt.toInstant();
return this;
}
public InstantBuilder next(WeekdayUnit unit) {
ZonedDateTime zdt = ZonedDateTime.ofInstant(current, zone);
current = zdt.with(TemporalAdjusters.next(unit.getUnit())).toInstant();
return this;
//current = current.with(TemporalAdjusters.next(unit.getUnit()));
/*
in(1, day());
int dow = current.get(ChronoField.DAY_OF_WEEK);
int days = (unit.getField() - dow + 7) % 7;
return in(days, days());
*/
}
public InstantBuilder previous(WeekdayUnit unit) {
ZonedDateTime zdt = ZonedDateTime.ofInstant(current, zone);
current = zdt.with(TemporalAdjusters.previous(unit.getUnit())).toInstant();
return this;
//current = current.with(TemporalAdjusters.previous(unit.getUnit()));
/*
int dow = current.get(ChronoField.DAY_OF_WEEK);
int days = 7 - (unit.getField() - dow + 7) % 7;
return before(days, days());
*/
}
public InstantBuilder at(int hour, int minute, int second) {
truncate(day());
//current = current.with(ChronoField.HOUR_OF_DAY, hour).with(ChronoField.MINUTE_OF_HOUR, minute).with(ChronoField.SECOND_OF_MINUTE, second);
current = current.plus(hour, ChronoUnit.HOURS).plus(minute, ChronoUnit.MINUTES).plus(second, ChronoUnit.SECONDS);
return this;
}
public InstantBuilder at(String time) {
//TODO improve
String[] split = time.split(":");
int hour = Integer.valueOf(split[0]);
int min = Integer.valueOf(split[1]);
int sec = Integer.valueOf(split[2]);
return at(hour, min, sec);
}
public InstantBuilder atMidnight() {
return at(0, 0, 0);
}
public InstantBuilder atNoon() {
return at(12, 0, 0);
}
public long till(Date date) {
return date.getTime() - toLong();
}
public long till(Instant instant) {
return instant.toEpochMilli() - toLong();
}
/** Returns same as toStringLocal() */
@Override
public String toString() {
return toStringLocal();
}
/** Returns the time in local timezone and format */
public String toStringLocal() {
return toStringLocal(DATE_FORMAT_LOCAL);
}
public String toStringUtc() {
return getFormater(DATE_FORMAT_UTC, "UTC").format(current);
}
public String toStringLocal(String format) {
return toString(ZONE_LOCAL, format);
}
public String toStringUtc(String format) {
return toString(ZONE_UTC, format);
}
protected String toString(ZoneId zoneId, String format) {
ZonedDateTime zdt = ZonedDateTime.ofInstant(current, ZONE_UTC);
return getFormater(format, zoneId.getId()).format(zdt);
}
public long toLong() {
return current.toEpochMilli();
}
public Instant toInstant() {
return current;
}
public Date toDate() {
return Date.from(current);
}
/** Returns the instant as ZonedDateTime with UTC as ZoneId */
public ZonedDateTime toZdt() {
return toZdt(ZONE_UTC);
}
public ZonedDateTime toZdt(ZoneId zoneId) {
return ZonedDateTime.ofInstant(current, zoneId);
}
}
/** Units as own enum for better code-completition support (instead of having ints everywhere) */
public static enum DatetimeUnit {
//TODO nanos(Calendar.MILLISECOND, ChronoUnit.MILLIS),
millis(Calendar.MILLISECOND, ChronoUnit.MILLIS),
seconds(Calendar.SECOND, ChronoUnit.SECONDS),
minutes(Calendar.MINUTE, ChronoUnit.MINUTES),
hours(Calendar.HOUR_OF_DAY, ChronoUnit.HOURS),
day(Calendar.DAY_OF_YEAR, ChronoUnit.DAYS),
week(Calendar.WEEK_OF_YEAR, ChronoUnit.WEEKS),
month(Calendar.MONTH, ChronoUnit.MONTHS),
year(Calendar.YEAR, ChronoUnit.YEARS);
private final int field;
private TemporalUnit unit;
private DatetimeUnit(int field, TemporalUnit unit) {
this.field = field;
this.unit = unit;
}
public int getField() {
return field;
}
public TemporalUnit getUnit() {
return unit;
}
}
/** Units as own enum for better code-completition support (instead of having ints everywhere) */
public static enum WeekdayUnit {
monday(Calendar.MONDAY, DayOfWeek.MONDAY),
tuesday(Calendar.TUESDAY, DayOfWeek.TUESDAY),
wednesday(Calendar.WEDNESDAY, DayOfWeek.WEDNESDAY),
thursday(Calendar.THURSDAY, DayOfWeek.THURSDAY),
friday(Calendar.FRIDAY, DayOfWeek.FRIDAY),
saturday(Calendar.SATURDAY, DayOfWeek.SATURDAY),
sunday(Calendar.SUNDAY, DayOfWeek.SUNDAY);
private final int field;
private DayOfWeek unit;
private WeekdayUnit(int field, DayOfWeek unit) {
this.field = field;
this.unit = unit;
}
public int getField() {
return field;
}
public DayOfWeek getUnit() {
return unit;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy