问题
This question solves the case for seconds: How to convert a date time string to long (UNIX Epoch Time) in Java 8 (Scala)
But if I want milliseconds it seems I have to use
def dateTimeStringToEpoch(s: String, pattern: String): Long =
LocalDateTime.parse(s, DateTimeFormatter.ofPattern(pattern))
.atZone(ZoneId.ofOffset("UTC", ZoneOffset.ofHours(0)))
.toInstant().toEpochMilli
which is ugly for the 4 issues I detail in the other question (main things I don't like is the magic literal "UTC"
and the magic number 0
).
Unfortunately the following does not compile
def dateTimeStringToEpoch(s: String, pattern: String): Long =
LocalDateTime.parse(s, DateTimeFormatter.ofPattern(pattern))
.toEpochMilliSecond(ZoneOffset.UTC)
as toEpochMilliSecond
does not exist
回答1:
Could you not use LocalDateTime#atOffset and ZoneOffset#UTC?
LocalDateTime.parse(s, dateTimeFormatter).atOffset(ZoneOffset.UTC).toInstant().toEpochMilli()
As @Andreas points out in the comments, ZoneOffset
is-a ZoneId
, so you could use
def dateTimeStringToEpoch(s: String, pattern: String): Long =
LocalDateTime.parse(s, DateTimeFormatter.ofPattern(pattern))
.atZone(ZoneOffset.UTC)
.toInstant()
.toEpochMilli()
回答2:
You can change this answer to return epoch millis like
static long dateTimeStringToEpoch(String s, String pattern) {
return DateTimeFormatter.ofPattern(pattern).withZone(ZoneOffset.UTC)
.parse(s, Instant::from).toEpochMilli();
}
Or, if you even want to avoid the construction of a temporary Instant
:
static long dateTimeStringToEpoch(String s, String pattern) {
return DateTimeFormatter.ofPattern(pattern).withZone(ZoneOffset.UTC)
.parse(s, ta -> ta.getLong(ChronoField.INSTANT_SECONDS)*1000
+ta.get(ChronoField.MILLI_OF_SECOND));
}
Note that both, DateTimeFormatter.ofPattern(pattern).withZone(ZoneOffset.UTC)
and ta -> ta.getLong(ChronoField.INSTANT_SECONDS)*1000+ta.get(ChronoField.MILLI_OF_SECOND)
are reusable components here, e.g. you could do
static final DateTimeFormatter MY_PATTERN
= DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").withZone(ZoneOffset.UTC);
static final TemporalQuery<Long> EPOCH_MILLIS
= ta -> ta.getLong(ChronoField.INSTANT_SECONDS)*1000+ta.get(ChronoField.MILLI_OF_SECOND);
and
long millis = MY_PATTERN.parse("2018-07-21 18:30", EPOCH_MILLIS);
The question is, how many different format strings do you expect to occur within you application. Usually, it’s not something that changes as often as the formatted dates you have to parse. It might be beneficial to create a cache mapping from format string to prepared DateTimeFormatter
. The lambda expression is a singleton anyway.
回答3:
When working with UNIX Epoch, I suggest using java.time.Instant
as it designed for epoch representation and takes UTC
into consideration by default, as it is part of the standard.
import java.time.Instant
object InstantFormat extends App {
//Instant.parse uses DateTimeFormatter.ISO_INSTANT
println(Instant.parse("2019-03-12T15:15:13.147Z"))
println(Instant.parse("2019-03-12T15:15:13Z"))
println(Instant.parse("2019-03-12T15:15:13Z").toEpochMilli)
println(Instant.parse("2019-03-12T15:15:13Z").getEpochSecond)
println(Instant.ofEpochMilli(1552403713147L))
println(Instant.ofEpochSecond(1552403713L))
}
outputs
2019-03-12T15:15:13.147Z
2019-03-12T15:15:13Z
1552403713000
1552403713
2019-03-12T15:15:13.147Z
2019-03-12T15:15:13Z
来源:https://stackoverflow.com/questions/55124653/how-to-convert-a-date-time-string-to-long-unix-epoch-time-milliseconds-in-java