问题
I have a Spring application and i receive a date from an angular client as a String, how can i convert this date to a Java Date, following is the TypeScript Date format :
TypeScript Date Format : Mon Jan 04 2021 00:00:00 GMT+0100 (Central European Standard Time)
Java Date Format : Mon Jan 04 00:00:00 CET 2021
回答1:
java.time
how can i convert this date to a Java Date, following is the TypeScript Date format :
TypeScript Date Format :
Mon Jan 04 2021 00:00:00 GMT+0100 (Central European Standard Time)
java.time
provides you with DateTimeFormatterBuilder
using which you can define a complex format for parsing/formatting as shown below:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.TextStyle;
import java.util.HashSet;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "Mon Jan 04 2021 00:00:00 GMT+0100 (Central European Standard Time)";
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("EEE MMM dd uuuu HH:mm:ss")
.appendLiteral(" ")
.appendZoneRegionId()
.appendOffset("+HHmm", "Z")
.appendLiteral(" (")
.appendZoneText(TextStyle.FULL)
.appendLiteral(")")
.toFormatter(Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
System.out.println(zdt);
}
}
Output:
2021-01-04T00:00+01:00[Europe/Paris]
Java Date Format :
Mon Jan 04 00:00:00 CET 2021
A date-time object is supposed to store the information about the date, time, timezone etc., not about the formatting. You can format a date-time object into a String
object with the pattern of your choice using date-time formatting API.
- The date-time formatting API for the modern date-time types is in the package,
java.time.format
e.g.java.time.format.DateTimeFormatter
,java.time.format.DateTimeFormatterBuilder
etc. - The date-time formatting API for the legacy date-time types is in the package,
java.text
e.g.java.text.SimpleDateFormat
,java.text.DateFormat
etc.
Given below is how you can format zdt
(obtained above) into a custom format:
DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z uuuu", Locale.ENGLISH);
String strDateTimeFormatted = zdt.format(dtfOutput);
System.out.println(strDateTimeFormatted);
Output:
Mon Jan 04 00:00:00 CET 2021
Learn about the modern date-time API from Trail: Date Time.
In case you want to convert zdt
(obtained above) into java.util.Date
, you can do so as shown below:
Date date = Date.from(zdt.toInstant());
System.out.println(date);
A note about the legacy date-time API:
The java.util.Date
object is not a real date-time object like the modern date-time types; rather, it represents the milliseconds from the Epoch of January 1, 1970
. When you print an object of java.util.Date
, its toString
method returns the date-time calculated from this milliseconds value. Since java.util.Date
does not have timezone information, it applies the timezone of your JVM and displays the same. If you need to print the date-time in a different timezone, you will need to set the timezone to SimpleDateFomrat
and obtain the formatted string from it.
3. The date-time API of java.util
and their formatting API, SimpleDateFormat
are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.
- For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7.
- If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
回答2:
Mon Jan 04 2021 00:00:00 GMT+0100 (Central European Standard Time)
This is an ambiguous timestamp. Political entities and the world at large is free to redefine what CEST means, at which point GMT+0100 means one thing, and CST means another. Furthermore, CEST has implications for any 'math' done on this date that are different from GMT+0100.
For example, if I want to know the date 6 months from that one, then if CST is leading, you'd want:
Thu Jul 04 2021 00:00:00 GMT+0200 (Central European Daylight Time)
or possibly you'd want that time but one hour earlier - another open question, there is no clear answer to that question inherent in the idea 'add 6 months to this timestamp', so you will have to specify it, because otherwise you get some random guess by the system, and you almost never want your computer / programming language to guess at a 50/50 concept like this.
If GMT+0100 is leading, you end up with:
Thu Jul 04 2021 00:00:00 GMT+0100 (Central European Standard Time)
Which is completely bizarre there are zero places on the entire planet where this timestamp makes sense as printed: Nobody is on CEST on the 4th of july, anywhere. It's a timestamp that is 'real', and yet used by literally 0 people.
Thus, before continuing, first you need to ask yourself which bits and bobs from what you do have, you want to preserve when you convert it. Note that there are 3 different ideas of time:
'solarflares' time: Commonly measured as millis-since-epoch. This is devoid of human concepts such as timezones. To record the exact instant in time that an event happened, or will happen, if the event is not a human appointment (i.e. when a solarflare is predicted to happen or did happen, hence the name 'solarflares' time). In java, best represented by
java.time.Instant
.'appointment' time: Commonly measured as a big sack of numbers: A year, a month, a day, hour, minute, second, and a timezone. And not one of those
GMT+0100
useless zones, but something likeEurope/Amsterdam
. Something likeCentral European Standard Time
is somewhat common, but also a very bad idea. These names have no clear meaning, something likeEurope/Amsterdam
is designed to most likely always have clear meaning, that's a proper zone. The idea is: Let's say you make an appointment with your dentist, in Amsterdam, for next month. It sure seems like a solarflares kind of deal, but it is not: if the netherlands decides to join a different timezone, the absolute # of seconds until your appointment changes along. Whereas that solarflare is not going to occur an hour earlier just because some political entity decreed it so.'alarm' time: Like appointment time but no zone info as a fundamental. If you set your alarm to wake you up at 8 in the morning and you hop in a plane and fly west a bunch, you want the alarm to still go off at 8 in the morning local time: The # of seconds until the alarm goes off should change as you move across zones.
So, what is your time value intended to represent?
If 'solarflares' time.
Then the job is to first convert this into a java.time.Instant
object, and take it from there. For example, convert back to appointment time via .atZone()
, and then print it to a string that looks like that using a java.time.format.DateTimeFormatter
. Imagine the input was in singapore time instead, then with this strategy the output is still in CET. Also, I get the feeling you showed the string not because you need the string to be formatted like that, but because you erroneously think that java stores time in this string format. It doesn't; java stores appointment time as an object with a field for year, month, day, etc. The printing of this to a string is separated out, and controlled by a formatter. You can make a formatter to print it any way you please.
Parsing this to a j.t.Instant
value can be done based on the GMT+0100
, you can ignore the CEST trailing text.
If 'appointments' time.
Then you need to parse this out which is non-trivial; the GMT+0100 is not what you wanted, that IS a legal zone, but not a useful one (no country in the CEST zone uses GMT+0100. There are places on the planet that are GMT+0100 year round. They are not, however, anywhere near central europe). Thus, the relevant bits are everthing except GMT+0100, including CEST, and that is not a standard date format, and 'Central European Standard Time' is not a thing java.time can recognize as far as I know. You'll need a table of all the possible strings that typescript can generate at that point.
If 'alarm time'
Then you can just stop parsing after the final :00
and toss the rest. Use a regexp to strip it out, then parse into a LocalDateTime
using the LocalDateTime.of(stringValue, formatter)
method. Easy enough.
A note of advice
Try to course your TypeScript to print this stuff in something other than that. One great way to do it is to combine solarflares time with an explicit zone (like Europe/Amsterdam
, not like Central European Standard Time
). This is much more easily reparsed into any of the 3 different conceptual ways to refer to time.
回答3:
You can use epoch time to share time between client and server, it´s an easy way.
Typescript epoch time management
const epoch = new Date().getTime();
console.log(epoch);
const date = new Date(epoch);
console.log(date);
Result:
1609801111672
Date Mon Jan 04 2021 22:58:31 GMT+0000 (Western European Standard Time)
Java epoch time management with java.util.Date
long epoch = new Date().getTime();
log.debug( "Epoch: {}", epoch );
Date date = new Date(epoch);
log.debug( "Date: {}", date );
Result
Epoch: 1609801111672
Date: 2021-01-04T22:58:31.672Z
来源:https://stackoverflow.com/questions/65564052/how-to-convert-typescript-date-to-a-java-date