| /* |
| * Copyright (c) 2022 Eike Stepper (Loehne, Germany) and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Eike Stepper - initial API and implementation |
| */ |
| package org.eclipse.emf.cdo.lm.internal.client; |
| |
| import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; |
| |
| import java.time.DateTimeException; |
| import java.time.Instant; |
| import java.time.LocalDate; |
| import java.time.LocalDateTime; |
| import java.time.LocalTime; |
| import java.time.ZoneId; |
| import java.time.ZonedDateTime; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| /** |
| * @author Eike Stepper |
| */ |
| public final class TimeStamp extends Number implements Comparable<TimeStamp> |
| { |
| public static final TimeStamp UNSPECIFIED_DATE = new TimeStamp(CDOBranchPoint.UNSPECIFIED_DATE); |
| |
| private static final Pattern PATTERN = Pattern.compile("(\\d{8}|\\d{6}|\\d{4})(-(\\d{2}(\\d{2}(\\d{2})?)?)(-(\\d{1,3}))?)?"); |
| |
| private static final int NANOS_PER_MILLI = 1000 * 1000; |
| |
| private static final ZoneId ZONE_ID = ZoneId.systemDefault(); |
| |
| private static final long serialVersionUID = 1L; |
| |
| private final long value; |
| |
| public TimeStamp() |
| { |
| this(System.currentTimeMillis()); |
| int MoveToNet4jUtil; |
| } |
| |
| public TimeStamp(String string) throws DateTimeException |
| { |
| this(parseTimeStamp(string)); |
| } |
| |
| public TimeStamp(long value) |
| { |
| this.value = value; |
| } |
| |
| @Override |
| public long longValue() |
| { |
| return value; |
| } |
| |
| @Override |
| public int intValue() |
| { |
| return (int)value; |
| } |
| |
| @Override |
| public float floatValue() |
| { |
| return value; |
| } |
| |
| @Override |
| public double doubleValue() |
| { |
| return value; |
| } |
| |
| @Override |
| public byte byteValue() |
| { |
| return (byte)value; |
| } |
| |
| @Override |
| public short shortValue() |
| { |
| return (short)value; |
| } |
| |
| @Override |
| public int compareTo(TimeStamp obj) |
| { |
| return compare(value, obj.value); |
| } |
| |
| @Override |
| public int hashCode() |
| { |
| return hashCode(value); |
| } |
| |
| @Override |
| public boolean equals(Object obj) |
| { |
| if (obj instanceof TimeStamp) |
| { |
| return value == ((TimeStamp)obj).longValue(); |
| } |
| |
| return false; |
| } |
| |
| @Override |
| public String toString() |
| { |
| return toString(value); |
| } |
| |
| private static void pad(StringBuilder builder, int value, int length) |
| { |
| String string = Integer.toString(value); |
| |
| int fill = length - string.length(); |
| for (int i = 0; i < fill; i++) |
| { |
| builder.append('0'); |
| } |
| |
| builder.append(string); |
| } |
| |
| private static String exceptionMessage(String string) |
| { |
| return "Invalid time stamp format: \"" + string + "\""; |
| } |
| |
| public static int compare(long x, long y) |
| { |
| return Long.compare(x, y); |
| } |
| |
| public static int hashCode(long value) |
| { |
| return Long.hashCode(value); |
| } |
| |
| public static String toString(long value) |
| { |
| LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(value), ZONE_ID); |
| |
| StringBuilder builder = new StringBuilder(19); |
| pad(builder, localDateTime.getYear(), 4); |
| pad(builder, localDateTime.getMonthValue(), 2); |
| pad(builder, localDateTime.getDayOfMonth(), 2); |
| builder.append('-'); |
| pad(builder, localDateTime.getHour(), 2); |
| pad(builder, localDateTime.getMinute(), 2); |
| pad(builder, localDateTime.getSecond(), 2); |
| builder.append('-'); |
| pad(builder, localDateTime.getNano() / NANOS_PER_MILLI, 3); |
| |
| return builder.toString(); |
| } |
| |
| public static long parseTimeStamp(String string) throws DateTimeException |
| { |
| Matcher matcher = PATTERN.matcher(string); |
| if (!matcher.matches()) |
| { |
| throw new DateTimeException(exceptionMessage(string)); |
| } |
| |
| try |
| { |
| String date = matcher.group(1); |
| if (date.length() == 4) |
| { |
| date = Integer.toString(LocalDate.now().getYear()) + date; |
| } |
| else if (date.length() == 6) |
| { |
| date = Integer.toString(LocalDate.now().getYear() / 100) + date; |
| } |
| |
| String time = matcher.group(3); |
| if (time == null) |
| { |
| time = "000000"; |
| } |
| else if (time.length() == 2) |
| { |
| time += "0000"; |
| } |
| else if (time.length() == 4) |
| { |
| time += "00"; |
| } |
| |
| String millis = matcher.group(7); |
| if (millis == null) |
| { |
| millis = "000"; |
| } |
| else if (millis.length() == 1) |
| { |
| millis = "00" + millis; |
| } |
| else if (millis.length() == 2) |
| { |
| millis = "0" + millis; |
| } |
| |
| int year = Integer.parseInt(date.substring(0, 4)); |
| int month = Integer.parseInt(date.substring(4, 6)); |
| int day = Integer.parseInt(date.substring(6, 8)); |
| LocalDate localDate = LocalDate.of(year, month, day); |
| |
| int hour = Integer.parseInt(time.substring(0, 2)); |
| int minute = Integer.parseInt(time.substring(2, 4)); |
| int second = Integer.parseInt(time.substring(4, 6)); |
| int nanos = Integer.parseInt(millis) * NANOS_PER_MILLI; |
| LocalTime localTime = LocalTime.of(hour, minute, second, nanos); |
| |
| LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime); |
| ZonedDateTime zonedDateTime = localDateTime.atZone(ZONE_ID); |
| return zonedDateTime.toInstant().toEpochMilli(); |
| } |
| catch (DateTimeException ex) |
| { |
| throw ex; |
| } |
| catch (Exception ex) |
| { |
| throw new DateTimeException(exceptionMessage(string), ex); |
| } |
| } |
| } |