-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathStixInstant.java
105 lines (87 loc) · 3.6 KB
/
StixInstant.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package io.digitalstate.stix.common;
import io.digitalstate.stix.helpers.StixDataFormats;
import java.time.Instant;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Stores a Java.time Instant and stores the original sub-second precision digital count.
* SubSecond precision count means that the number of digits (even if all zeros / trailing zeros) are remembered.
* Use toString() to get the Stix string format for the datetime.
*/
public class StixInstant {
public static final Pattern REGEX_SUBSECOND = Pattern.compile("(?<fullDate>\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(.(?<subSecond>[0-9]+))?Z)");
private final Instant instant;
private final int originalSubSecondPrecisionDigitCount;
/**
* Generates a Instant.now()
* Defaults to 3 digits of sub second precision (milliseconds)
*/
public StixInstant() {
Instant now = Instant.now();
this.instant = now;
this.originalSubSecondPrecisionDigitCount = 3;
}
public StixInstant(Instant instant, int subSecondPrecision) {
Objects.requireNonNull(instant);
if (subSecondPrecision < 0 || subSecondPrecision > 9){
throw new IllegalStateException("Subsecond precision must be between 0 and 9");
}
this.instant = instant;
this.originalSubSecondPrecisionDigitCount = subSecondPrecision;
}
/**
* Defaults with parsed Instant's Nano second precision digit count.
* Note that trailing zeros would have been stripped.
* If you need to keep exact precision, including the trailing zeros, use {@link StixInstant#StixInstant(Instant, int)}
* @param instant
*/
public StixInstant(Instant instant) {
this(instant, String.valueOf(instant.getNano()).length());
}
/**
* Get the underlying Instant value. If you need the Stix Date with the Stix Precision then use {@link StixInstant#toString()}
* getInstant() should only be used in special cases where you need access to perform temporal work.
* @return
*/
public Instant getInstant() {
return instant;
}
public int getOriginalSubSecondPrecisionDigitCount() {
return originalSubSecondPrecisionDigitCount;
}
/**
* Generates a STIX Spec String of DateTime.
* Uses {@link StixDataFormats#getWriterStixDateTimeFormatter(int)}
* @return
*/
@Override
public String toString() {
return StixDataFormats.getWriterStixDateTimeFormatter(originalSubSecondPrecisionDigitCount)
.format(this.instant);
}
public String toString(int subSecondPrecision) {
return StixDataFormats.getWriterStixDateTimeFormatter(subSecondPrecision)
.format(this.instant);
}
public static StixInstant parse(String dateString){
Objects.requireNonNull(dateString);
Instant instant = Instant.from(StixDataFormats.getReaderStixDateTimeFormatter().parse(dateString));
int subSecondPrecision = getSubSecondDigitCount(dateString);
return new StixInstant(instant, subSecondPrecision);
}
private static int getSubSecondDigitCount(String dateString){
Matcher matcher = REGEX_SUBSECOND.matcher(dateString);
if (matcher.find()){
String subSeconds = matcher.group("subSecond");
// If no sub seconds were provided then return 0 as the precision
if (subSeconds == null){
return 0;
} else {
return subSeconds.length();
}
} else {
throw new IllegalStateException("Unable to parse date");
}
}
}