1
15
16 package software.amazon.awssdk.utils;
17
18 import static java.time.ZoneOffset.UTC;
19 import static java.time.format.DateTimeFormatter.ISO_INSTANT;
20 import static java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME;
21
22 import java.math.BigDecimal;
23 import java.time.Duration;
24 import java.time.Instant;
25 import java.time.ZoneOffset;
26 import java.time.ZonedDateTime;
27 import java.time.format.DateTimeFormatter;
28 import java.time.format.DateTimeFormatterBuilder;
29 import java.time.format.DateTimeParseException;
30 import software.amazon.awssdk.annotations.SdkProtectedApi;
31 import software.amazon.awssdk.annotations.ThreadSafe;
32
33
36 @ThreadSafe
37 @SdkProtectedApi
38 public final class DateUtils {
39
40
43 static final DateTimeFormatter ALTERNATE_ISO_8601_DATE_FORMAT =
44 new DateTimeFormatterBuilder()
45 .appendPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")
46 .toFormatter()
47 .withZone(UTC);
48
49 private static final int MILLI_SECOND_PRECISION = 3;
50
51 private DateUtils() {
52 }
53
54
63 public static Instant parseIso8601Date(String dateString) {
64
65 if (dateString.endsWith("+0000")) {
66 dateString = dateString
67 .substring(0, dateString.length() - 5)
68 .concat("Z");
69 }
70
71 try {
72 return parseInstant(dateString, ISO_INSTANT);
73 } catch (DateTimeParseException e) {
74 return parseInstant(dateString, ALTERNATE_ISO_8601_DATE_FORMAT);
75 }
76 }
77
78
84 public static String formatIso8601Date(Instant date) {
85 return ISO_INSTANT.format(date);
86 }
87
88
97 public static Instant parseRfc1123Date(String dateString) {
98 if (dateString == null) {
99 return null;
100 }
101 return parseInstant(dateString, RFC_1123_DATE_TIME);
102 }
103
104
112 public static String formatRfc1123Date(Instant instant) {
113 return RFC_1123_DATE_TIME.format(ZonedDateTime.ofInstant(instant, UTC));
114 }
115
116
120 public static long numberOfDaysSinceEpoch(long milliSinceEpoch) {
121 return Duration.ofMillis(milliSinceEpoch).toDays();
122 }
123
124 private static Instant parseInstant(String dateString, DateTimeFormatter formatter) {
125 return formatter.withZone(ZoneOffset.UTC).parse(dateString, Instant::from);
126 }
127
128
131 public static Instant parseUnixTimestampInstant(String dateString) throws NumberFormatException {
132 if (dateString == null) {
133 return null;
134 }
135 BigDecimal dateValue = new BigDecimal(dateString);
136 return Instant.ofEpochMilli(dateValue.scaleByPowerOfTen(MILLI_SECOND_PRECISION).longValue());
137 }
138
139
142 public static Instant parseUnixTimestampMillisInstant(String dateString) throws NumberFormatException {
143 if (dateString == null) {
144 return null;
145 }
146 return Instant.ofEpochMilli(Long.parseLong(dateString));
147 }
148
149
152 public static String formatUnixTimestampInstant(Instant instant) {
153 if (instant == null) {
154 return null;
155 }
156 BigDecimal dateValue = BigDecimal.valueOf(instant.toEpochMilli());
157 return dateValue.scaleByPowerOfTen(0 - MILLI_SECOND_PRECISION)
158 .toPlainString();
159 }
160 }
161