Convert epoch to date with fractional seconds with Java [duplicate] - java

This question already has answers here:
How to include milliseconds in a formatted date string?
(3 answers)
Closed 5 years ago.
I have a date that I want to change into a different format.
Current format: Fri Apr 07 08:21:19 MDT 2017
Desired format: 2017-04-07T13:28:41.00MDT. I want to have the desired format output as a string.
I am currently doing this:
DateTimeFormatter sourceFormat = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z uuuu");
ZonedDateTime dateParsed = ZonedDateTime.parse(dateStr, sourceFormat);
String fullDateTimeStr = fullDateTime.format(dateParsed);
The formatting is correct, but the main issue I'm having is preserving the fractional seconds (the two numbers right before the time zone.) I know that the date I am receiving has the ms/fractional seconds preserved because when I print out long epoch = ((Date) date).getTime(); I get the epoch time and I can convert it (using an online conversion tool) and it shows the correct date/time with ms.
What's going on?

DateTimeFormatter targetFormat = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSz");
ZonedDateTime zdt = ZonedDateTime.now();
System.out.println(zdt.format(targetFormat));
Sample output:
2017-04-14T21:19:58.409CEST
You need SSS in the format pattern for the milliseconds.
Please consider whether you need the three or four letter time zone abbreviations that are often ambiguous. I would prefer to use DateTimeFormatter.ISO_ZONED_DATE_TIME for an output like 2017-04-14T21:22:49.344+02:00[Europe/Berlin]. This also saves you from building the pattern string yourself.

Related

DateTimeFormatter adding a year to date after formatting [duplicate]

This question already has answers here:
Why does Java's java.time.format.DateTimeFormatter#format(LocalDateTime) add a year?
(2 answers)
Using DateTimeFormatter on january first cause an invalid year value
(1 answer)
Closed 3 years ago.
I am trying to convert a date of the format 2019-12-30 to a date with format 30-12-2019 and for this I thought of using DateTimeFormatter and I have the following code for this:
LocalDate date = LocalDate.parse("2019-12-30");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-YYYY");
System.out.println(formatter.format(date));
However, to my surprise, this returns an output:
30-12-2020
instead of the expected 30-12-2019. If the date is set to 2019-11-30, it correctly returns 30-11-2019. I am doing something terribly wrong but I am not able to figure out what exactly. Can someone please help?
From the DateTimeFormatter documentation:, indicating the symbol, meaning and examples:
Y week-based-year year 1996; 96
So you're formatting the week-based-year, not the regular year. December 30th 2019 belongs to the first week of 2020, hence your output.
Use yyyy (year-of-era) or uuuu (year) instead of YYYY and you'll get 2019 instead.
Basically, YYYY should usually be used with w (week-of-week-based-year) and E (day-of-week).
Use "dd-MM-yyyy" instead of "dd-MM-YYYY"
Try the following code snippet to get expected result -
LocalDate date = LocalDate.parse("2019-12-30");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
System.out.println("date " + formatter.format(date)); // date 30-12-2019
You are using DateTimeFormatter.ofPattern("dd-MM-YYYY"); and notice that Y stands for week-based-year, which you probably don't want. Perhaps you want yout pattern to be "dd-MM-uuuu". For more information on patterns, refer to the official Oracle documentation: Patterns for Formatting and Parsing

converting from string to date object not displaying expected result [duplicate]

This question already has answers here:
How to Parse Date from GMT TimeZone to IST TimeZone and Vice Versa in android
(4 answers)
SimpleDateFormat returns wrong time zone during parse
(2 answers)
DateFormat parse - not return date in UTC
(1 answer)
Closed 3 years ago.
I searched for solutions but still not working ,I'm trying to convert the date object's local timezone to UTC +0 , but when i format the date object to UTC it's working . but when I want to convert the converted string to date again, the format changes and UTC goes back to GMT+8 before i store it in the fire store. what is the problem in the code?
this is the current date object that i get
Calendar time = Calendar.getInstance();
time.setTimeZone(TimeZone.getTimeZone("UTC"));
Date current_time = time.getTime();
if printed
Thu Aug 22 10:09:55 GMT+08:00 2019
then i convert it to UTC
String dismissal_time_firestore;
Log.i(TAG, "Current time when swiped from phone time.getTime() "+current_time);
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
dismissal_time_firestore = dateFormat.format(current_time);
got this
Thu, 22 Aug 2019 02:09:55 +0000
but then when i convert this string to a date object
try {
current_time = dateFormat.parse(dismissal_time_firestore);
} catch (ParseException e) {
e.printStackTrace();
}
i got this
Thu Aug 22 10:09:55 GMT+08:00 2019
You are using terrible date-time classes that were supplanted years ago by the modern java.time classes defined in JSR 310.
Your main problem is not understanding that the Date::toString method lies to you. It dynamically applies the JVM’s current time zone to the moment in UTC while generating the text. One of many reasons to never use this class.
Get current moment in UTC.
Instant instant = Instant.now() ;
View that moment as seen in the wall-clock time used by the people of a particular region (a time zone).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Generate text for display to user.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ;
String output = zdt.format( f ) ;
You talk about parsing formatted strings. Bad idea. Think of textual representations of date-time values only as outputs, not inputs. Collecting date-time inputs should be done by using date-time widgets, not typed text.
When storing or exchanging date-time values as text, always use ISO 8601 standard formats. The java.time classes use ISO 8601 formats by default when parsing/generating strings. So no need to specify any formatting pattern. Just call parse/toString. Example: Instant.now().toString() and Instant.parse( "2020-01-23T12:34:56.123456Z" ).
I cannot help further as you did not really say what you were trying to accomplish.
All of this has been covered many many times on Stack Overflow. So search to learn more. And search before posting.

How to Change time format of date string using timeoffset [duplicate]

This question already has answers here:
Strange Java Timezone Date Conversion Problem
(3 answers)
Closed 4 years ago.
I am trying to convert date string to UTC format from another time zone in Java. we have only time zone offset like "-06:00". Can any one help me how to convert the date time to UTC format using time zone offset.
Thanks
This for java version 1.7 . I have tried with following snippet but receiving the same input as output.
String dateInString = "02/04/2019 18:17:15";
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = formatter.parse(dateInString);
DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("+5:30"));
String dateStr = dateFormat.format(date);
System.out.println(dateStr);
Output
02/04/2019 18:17:15
Unfortunately, TimeZone.getTimeZone(String ID) returns:
the specified TimeZone, or the GMT zone if the given ID cannot be understood.
The "+5:30" time zone cannot be understood, so you get GMT.
Change to "GMT+5:30" will make your code work, i.e. it'll print:
02/04/2019 23:47:15
See the javadoc of TimeZone for valid ID syntax:
The syntax of a custom time zone ID is:
CustomID:
GMT Sign Hours : Minutes
GMT Sign Hours Minutes
GMT Sign Hours
Sign: one of
+ -
Hours:
Digit
Digit Digit
Minutes:
Digit Digit
Digit: one of
0 1 2 3 4 5 6 7 8 9
As you can see, it must always start with GMT.

Conversion of a date to epoch Java [duplicate]

This question already has answers here:
SimpleDateFormat producing wrong date time when parsing "YYYY-MM-dd HH:mm"
(5 answers)
Closed 4 years ago.
I want to convert 2018-02-21 15:47:35 UTC to epoch UTC form. How do we do it? I am currently in PST.
SimpleDateFormat df = new SimpleDateFormat("YYYY-MM-DD HH:MM:SS");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
date = df.parse(dateString).getTime();
The code above should return the number of milliseconds since January 1, 1970, 00:00:00 GMT, but I'm getting an incorrect value.
The only problem with your code is DateFormat
please check.
https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
String dateString = "2018-02-21 15:47:35";
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = df.parse(dateString);
long time = date.getTime();
System.out.println(time);
System.out.println(new Date(time));
System.out.println(date);
I'm in PKT so output would differ...
1519228055000
Wed Feb 21 20:47:35 PKT 2018
Wed Feb 21 20:47:35 PKT 2018
Expected: 2018-02-21 15:47:35 UTC is equivalent to 1 519 228 055 000 milliseconds since the epoch of January 1, 1970 at 0:00 UTC.
Observed: Your code in the question gives 1 514 818 800 035. So it’s 4 409 254 965 milliseconds off, a little over 51 days.
The solution:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
date = LocalDateTime.parse("2018-02-21 15:47:35", dtf)
.atOffset(ZoneOffset.UTC)
.toInstant()
.toEpochMilli();
This gives the correct 1 519 228 055 000.
What went wrong?
One of the many troublesome traits of SimpleDateFormat is that with its default settings, if you specify an incorrect format pattern string, it will very often give you an incorrect result and pretend all is well. The modern Java date and time API that I am using in my snippet, is trying somewhat harder to figure out when the pattern doesn’t make sense and tell you it’s wrong somehow. As an example, let’s try your format pattern with the modern DateTimeFormatter:
final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("YYYY-MM-DD HH:MM:SS");
LocalDateTime.parse(dateString, dtf);
This will throw a java.time.format.DateTimeParseException: Text '2018-02-21 15:47:35' could not be parsed at index 14. Index 14 is where 47 is in the string, it was supposed to be the minutes. Apparently 47 doesn’t match MM in the format. If you haven’t figured out yet, check the documentation. It says that uppercase M is for “month-of-year”. So what the formatter is trying to tell you is there are not 47 months in a year. In the documentation you will also find lowercase m for “minute-of-hour”. As you correct the case of the letters in the format pattern string, you will receive other exceptions until you end up with either yyyy-MM-dd HH:mm:ss or uuuu-MM-dd HH:mm:ss (lowercase yyyy is year or era while uuuu is a signed year, both work for years after year 0).
Links
Oracle tutorial: Date Time explaining how to use java.time.
DateTimeFormatter documentation spelling out the uppercase and lowercase letters of format pattern strings.
Also can be done via java8 time library:
String dateString = "2018-02-21 15:47:35";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
dateTimeFormatter.withZone(ZoneId.of("UTC"));
LocalDateTime parsedDateTime = LocalDateTime.from(dateTimeFormatter.parse(dateString));
ZonedDateTime timeAtYourZone = parsedDateTime.atZone(ZoneId.systemDefault());
System.out.println(timeAtYourZone.toInstant().toEpochMilli());
System.out.println(timeAtYourZone);
Your pattern must be yyyy-MM-dd HH:mm:ss, as the other answers told you:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
I just want to add some more details.
First of all, take a look at the patterns description in the javadoc: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
Note that a lowercase y is not the same as the uppercase Y (lowercase is the year, while uppercase is the week year - 2 different fields with completely different definitions)
Also note that uppercase D is the day of the year, while the day of the month (which is what you want) is the lowercase d. And uppercase M is the month, while lowercase m is the minute of hour.
And uppercase S is the milliseconds field, while the seconds are represented by lowercase s.
And SimpleDateFormat's design doesn't help: the class simply tries to parse the string, even if the month field (MM) appears twice in your pattern, while the minutes field doesn't appear (and it's set to a default value of zero - all behind the scenes, without any warning, no indication of error at all).
Conclusion: always read the docs :-)
For Java 8 or higher, consider using the new date API, which is much better because it doesn't have all these behind-the-scenes stuff:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
.withZone(ZoneOffset.UTC);
long epochMilli = Instant.from(fmt.parse("2018-02-21 15:47:35")).toEpochMilli();
This API will also throw an exception if you use a pattern like YYYY-MM-DD HH:MM:SS, because it will try to parse the minutes value 47 as a month (because uppercase MM will be in the respective position), and 47 is not a valid month.

Convert unix timestamp to date in java [duplicate]

This question already has answers here:
Unix epoch time to Java Date object
(7 answers)
Closed 5 years ago.
How can I convert minutes from Unix timestamp to date and time in java? For example, timestamp 1372339860 correspond to Thu, 27 Jun 2013 13:31:00 GMT.
I want to convert 1372339860 to 2013-06-27 13:31:00 GMT.
Edit: Actually I want it to be according to US timing GMT-4, so it will be 2013-06-27 09:31:00.
You can use SimlpeDateFormat to format your date like this:
long unixSeconds = 1372339860;
// convert seconds to milliseconds
Date date = new java.util.Date(unixSeconds*1000L);
// the format of your date
SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
// give a timezone reference for formatting (see comment at the bottom)
sdf.setTimeZone(java.util.TimeZone.getTimeZone("GMT-4"));
String formattedDate = sdf.format(date);
System.out.println(formattedDate);
The pattern that SimpleDateFormat takes if very flexible, you can check in the javadocs all the variations you can use to produce different formatting based on the patterns you write given a specific Date. http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
Because a Date provides a getTime() method that returns the milliseconds since EPOC, it is required that you give to SimpleDateFormat a timezone to format the date properly acording to your timezone, otherwise it will use the default timezone of the JVM (which if well configured will anyways be right)
Java 8 introduces the Instant.ofEpochSecond utility method for creating an Instant from a Unix timestamp, this can then be converted into a ZonedDateTime and finally formatted, e.g.:
final DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
final long unixTime = 1372339860;
final String formattedDtm = Instant.ofEpochSecond(unixTime)
.atZone(ZoneId.of("GMT-4"))
.format(formatter);
System.out.println(formattedDtm); // => '2013-06-27 09:31:00'
I thought this might be useful for people who are using Java 8.
You need to convert it to milliseconds by multiplying the timestamp by 1000:
java.util.Date dateTime=new java.util.Date((long)timeStamp*1000);

Categories

Resources