I have a string - 20180915 in format yyyyMMdd
I need to get epoch milli seconds for this date, answer for 20180915 should be 1537012800000
I was able to do this using following function -
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
public static void main(String args[]) throws ParseException {
String myDate = "2018-09-15 12:00:00";
LocalDateTime localDateTime = LocalDateTime.parse(myDate,
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") );
System.out.println(localDateTime);
long millis = localDateTime
.atZone(ZoneOffset.UTC)
.toInstant().toEpochMilli();
System.out.println(millis);
}
The problem I am facing is -
I am passing String as "2018-09-15 12:00:00" but my input is "20180915".
I am unable to find good way to convert "20180915" to "2018-09-15 12:00:00"
How can i achieve this ?
Answer -
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
public static Long getMillisForDate(String date) {
return LocalDateTime
.of(LocalDate.parse(date, formatter), LocalTime.NOON)
.atZone(ZoneOffset.UTC)
.toInstant().toEpochMilli();
}
You can make the DateTimeFormatter do all the work, which is especially useful if you need to parse multiple dates, as it reduces the number of intermediate parsing steps (and objects created):
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
.appendPattern("uuuuMMdd")
.parseDefaulting(ChronoField.HOUR_OF_DAY, 12)
.toFormatter()
.withZone(ZoneOffset.UTC);
String input = "20180915";
long epochMilli = OffsetDateTime.parse(input, fmt).toInstant().toEpochMilli();
System.out.println(epochMilli); // prints: 1537012800000
You can replace OffsetDateTime with ZonedDateTime. Makes no difference to the result.
Parse the date with proper mask "yyyyMMdd"
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
Date date = format.parse("20180915");
long epochs = date.getTime();
Related
I get a timestamp in the format "20210908094049.884Z". This is the last modify timestamp from an LDAP object. I use Spring Boot Ldap. I have no clue how to parse this String in a Datetime like dd.MM.yyyy HH:mm.
Can anyone help me please?
Here is an example:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Main {
public static void main(String[] args) {
// Creating new simple date formatter with the format you've given
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
// Defining the input date
String inputDate = "20210908094049.884Z";
// Parsing the date, catching the parse exception if date is malformatted
Date date = null;
try {
// Date ends on a Z, we remove this Z (Z is for timezone UTC +0:00)
date = format.parse(inputDate.replace("Z", ""));
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
Giving following output:
Wed Sep 08 09:40:49 CEST 2021
Edit:
Here another even better solution from Ole V.V.
import java.time.Instant;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
Instant instant = DateTimeFormatter
// Defining pattern to parse
.ofPattern("yyyyMMddHHmmss.SSSXX")
// Defining input to parse with pattern
.parse("20210908094049.884Z", Instant::from);
System.out.println(instant);
}
}
Output is an instant with value:
2021-09-08T09:40:49.884Z
java.time
I recommend that you use java.time, the modern Java date and time API, for your work with timestamps.
The LDAP timestamp format has a number of allowed variations (see the link at the bottom). The following formatter takes many of them into account, not all of them.
private static final DateTimeFormatter LDAP_PARSER = new DateTimeFormatterBuilder()
.appendPattern("uuuuMMddHHmmss")
.optionalStart()
.appendPattern("[.][,]")
.appendFraction(ChronoField.NANO_OF_SECOND, 1, 9, false)
.optionalEnd()
.appendPattern("[XX][X]")
.toFormatter(Locale.ROOT);
With this formatter we may for example parse your string into an OffsetDateTime:
String ldapTimestampString = "20210908094049.884Z";
OffsetDateTime timestamp = OffsetDateTime.parse(ldapTimestampString, LDAP_PARSER);
System.out.println(timestamp);
Output is:
2021-09-08T09:40:49.884Z
Formatting
To convert the timestamp to a string containing date and time you need to decide on a time zone for that since it is never the same date nor the same time in all time zones.
Use this formatter:
private static final DateTimeFormatter FORMATTER
= DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
Then do:
ZoneId zone = ZoneId.of("Pacific/Tarawa");
ZonedDateTime dateTime = timestamp.atZoneSameInstant(zone);
String formattedDateTime = dateTime.format(FORMATTER);
System.out.println(formattedDateTime);
08.09.2021 21:40
Links
Oracle tutorial: Date Time explaining how to use java.time.
GeneralizedTime on ldapwiki defining the LDAP timestamp format.
I am trying to convert java String date into java.sql.Timestamp. I am able to convert this by using SimpleDateFormat with String date value as "2021-01-07 02:02:16.172", but when trying with the value as "2021-08-04T00:00:00.000" with seperator 'T', it gives me error. Below is the java code:
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateTest {
public static void main(String[] args) throws ParseException {
//String date = "2021-08-04T00:00:00.000Z";// How to convert this?
String date = "2021-01-07 02:02:16.172";// conversion successful
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
Date parsedDate = dateFormat.parse(date);
Timestamp timestamp = new java.sql.Timestamp(parsedDate.getTime());
System.out.println(timestamp);
}
}
You could use the modern API for dates, times and related information (like offsets from UTC): java.time
Strings in different formats need to be handled differently:
your first example String is formatted in ISO standard, so it can be parsed without defining a custom format. The parsing implicitly uses a DateTimeFormatter.ISO_OFFSET_DATE_TIME, which will result in an OffsetDateTime
your seconds String lacks the 'T' between date and time as well as an offset, that means you can just directly parse it to a LocalDateTime
java.sql.Timestamp got methods for conversion to java.time classes, at least to/from an Instant and a LocalDateTime. Since an Instant is a well defined moment in time, you can derive it from an OffsetDateTime:
public static void main(String[] args) throws Exception {
// your two example datetimes
String isoDateTime = "2021-08-04T00:00:00.000Z";
String customDateTime = "2021-01-07 02:02:16.172";
// you will need a custom formatter for the second one
DateTimeFormatter customDtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS");
// parse the Strings to java.time objects
// ISO standard, no extra formatter needed for the first one
OffsetDateTime odt = OffsetDateTime.parse(isoDateTime);
// the second one requires the formatter defined above
LocalDateTime ldt = LocalDateTime.parse(customDateTime, customDtf);
// convert them into Timestamps
Timestamp tsOne = Timestamp.from(odt.toInstant());
Timestamp tsTwo = Timestamp.valueOf(ldt);
// and print them
System.out.println("First Timestamp: " + tsOne);
System.out.println("Second Timestamp: " + tsTwo);
}
The output of this is
First Timestamp: 2021-08-04 02:00:00.0
Second Timestamp: 2021-01-07 02:02:16.172
This would be the new style...
new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS");
would be the old style
Given:
public static void main(String[] args) {
String dateString = "2018-07-30T13:36:17.820";
DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter
.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
LocalDate date = LocalDate.parse(dateString, DATE_TIME_FORMATTER);
ZonedDateTime zonedDateTime = date.atStartOfDay((ZoneOffset.UTC));
System.out.println(zonedDateTime);
}
And output:
2018-07-30T00:00Z
...what is the pattern to print seconds? Stupid question no doubt but driving me a little nuts
I need:
2018-07-30T00:00:00Z
I changed java.time.LocalDate to java.time.LocalDateTime, you need it if you want to show also the seconds.
package com.test;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class DateFormatter {
public static void main(String[] args) {
String dateString = "2018-07-30T13:36:17.820";
DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter
.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
LocalDateTime date = LocalDateTime.parse(dateString, DATE_TIME_FORMATTER);
ZonedDateTime zonedDateTime = date.atZone(ZoneOffset.UTC);
System.out.println(zonedDateTime);
}
}
Output is:
2018-07-30T13:36:17.820Z
LocalDate will keep just date. You need to parse LocalDateTime and convert to ZonedDateTime and you will have seconds as you expect.
var dateString = "2018-07-30T13:36:17.820";
var format = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
var localDate = LocalDateTime.parse(dateString, format);
var zone = ZoneId.of( "America/Montreal" );
var zonedDateTime = localDate.atZone(zone);
System.out.println(zonedDateTime);
You will have to go a few steps:
parse the String to a LocalDateTime because it contains date and time of day
extract the date only
create a ZonedDateTime out of that by adding the start of day (LocalTime.MIN = 00:00:00) and a ZoneOffset.UTC
This code may do:
public static void main(String[] args) {
String dateString = "2018-07-30T13:36:17.820";
// parse a LocalDateTime
LocalDateTime localDateTime = LocalDateTime.parse(dateString);
// extract the date part
LocalDate localDate = localDateTime.toLocalDate();
// make it a ZonedDateTime by applying a ZoneId
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDate, LocalTime.MIN, ZoneOffset.UTC);
// print the result
System.out.println(zonedDateTime.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
}
Output is
2018-07-30T00:00:00Z
There are several ways to do it, this is just one of them and it just slightly differs from most of the other answers (and comments :-) ).
tl;dr
You have used the wrong things in the wrong places.
You do not need a DateTimeFormatter explicitly in order to parse 2018-07-30T13:36:17.820 because it's already in ISO 8601 format which is also the default format used by LocalDateTime#parse. Moreover, this string has date and time instead of just date; therefore, it makes more sense to parse it into LocalDateTime instead of LocalDate. You can always get LocalDate from LocalDateTime using LocalDateTime#toLocalDate.
The ZonedDateTime#toString uses the LocalDateTime#toString which in turn uses LocalTime#toString for the time part which omits second and fraction-of-second if they are zero. If you need a string with zero second and fraction-of-second, you will need to use a DateTimeFormatter.
Demo:
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String args[]) {
String dateString = "2018-07-30T13:36:17.820";
LocalDateTime localDateTime = LocalDateTime.parse(dateString);// You do not need a DateTimeFormatter here
ZonedDateTime zonedDateTime = localDateTime.toLocalDate().atStartOfDay(ZoneOffset.UTC);
// Print zonedDateTime.toString()
System.out.println(zonedDateTime);
// Custom format
final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
System.out.println(DATE_TIME_FORMATTER.format(zonedDateTime));
}
}
Output:
2018-07-30T00:00Z
2018-07-30T00:00:00.000
Learn more about the modern date-time API from Trail: Date Time.
I have a Date variable lets say deliveryDate. It's saved in MonngoDB in this format.
ISODate("2020-10-07T03:10:00Z")
Now I want to change the time property of delivery Date. But it has to be done based on some String which tells what time to be set. for eg String time = "7:20 AM" [ this time is based of Kuala Lumpur, Malaysia ]. Then the result should be something like :
deliveryDate = ISODate("2020-10-07T11:20:00Z")
Some general note : 7:20 AM Monday, in Kuala Lumpur, Federal Territory of Kuala Lumpur, Malaysia is 11:20 PM Sunday, Coordinated Universal Time (UTC).
Now given the String time and Date delivery Date. How can I obtain the results above for all cases ?
The thing that I am expecting is :
public static Date adjustTimeOfDay(Date deliveryDate, String timeOfDay) {
// Adjust the time of the day of deliveryDate on the basis of timeOfDay
// Keep the offset and zone same while adjusting
return deliveryDate
}
You can use the compatibility method java.util.Date.toInstant(), manipulate the time of day of that Instant which creates a different Instant and then convert back to a Date by Date.from(Instant instant).
Here's an example method for the manipulation:
public static Instant adjustTimeOfDay(Instant instant, String timeOfDay) {
// convert the instant to an offset-aware datetime object
OffsetDateTime deliveryOdt = OffsetDateTime.ofInstant(instant, ZoneOffset.UTC);
/*
* provide a formatter that parses a time-of-day String.
* PLEASE NOT that this formatter is not very lenient,
* the String must be of the pattern "hh:mm a"
*/
DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendPattern("hh")
.appendLiteral(':')
.appendPattern("mm")
.appendLiteral(' ')
.appendPattern("a")
.parseCaseInsensitive()
.toFormatter();
// parse that String to a LocalTime
LocalTime localTime = LocalTime.parse(timeOfDay, dtf);
/*
* create a new OffsetDateTime
* adding the new LocalTime to the old LocalDate at UTC
*/
OffsetDateTime adjustedOdt = OffsetDateTime.of(deliveryOdt.toLocalDate(),
localTime,
ZoneOffset.UTC);
return adjustedOdt.toInstant();
}
I used in a main like this:
public static void main(String[] args) {
/*
* instead of creating a Date,
* I directly use Instant here and parse your example String,
* so just use your deliveryDate.toInstant()
*/
String input = "2020-10-07T03:10:00Z";
Instant instant = Instant.parse(input);
// then take a time of day to be set
String timeOfDayUpdate = "07:20 AM";
Instant adjusted = adjustTimeOfDay(instant, timeOfDayUpdate);
System.out.println(input + " ==> " + OffsetDateTime.ofInstant(adjusted, ZoneOffset.UTC)
.format(DateTimeFormatter.ISO_INSTANT));
}
which created the following output:
2020-10-07T03:10:00Z ==> 2020-10-07T07:20:00Z
EDIT
You can rewrite that method to
public static Date adjustTimeOfDay(Date date, String timeOfDay) {
// convert the date to an instant and the instant to an offset-aware datetime object
OffsetDateTime deliveryOdt = OffsetDateTime.ofInstant(date.toInstant(), ZoneOffset.UTC);
// provide a formatter that parses a time-of-day String
DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendPattern("hh")
.appendLiteral(':')
.appendPattern("mm")
.appendLiteral(' ')
.appendPattern("a")
.parseCaseInsensitive()
.toFormatter();
// parse that String to a LocalTime
LocalTime localTime = LocalTime.parse(timeOfDay, dtf);
/*
* create a new OffsetDateTime
* adding the new LocalTime to the old LocalDate at UTC
*/
OffsetDateTime adjustedOdt = OffsetDateTime.of(deliveryOdt.toLocalDate(),
localTime,
ZoneOffset.UTC);
// return a Date from the Instant you get out of the OffsetDateTime
return Date.from(adjustedOdt.toInstant());
}
passing a Date and getting one returned.
If I understood your requirement correctly, you are looking for something like:
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
// Test
System.out.println(adjustTimeOfDay("2020-10-07T03:10:00Z", "7:20 AM"));
}
public static String adjustTimeOfDay(String deliveryDate, String timeOfDay) {
// Define the formatter to parse time like 7:20 AM
DateTimeFormatter timeFormatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("h:m a")
.toFormatter(Locale.ENGLISH);
return ZonedDateTime.parse(deliveryDate)
.toLocalDate()
.atTime(LocalTime.parse(timeOfDay, timeFormatter))
.atZone(ZoneId.of("Asia/Kuala_Lumpur"))
.withZoneSameInstant(ZoneOffset.UTC)
.format(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss")) + 'Z';
}
}
Output:
2020-10-06T23:20:00Z
I recommend you use use HH for a time in 24-hour format. However, if you want to get a time string by ignoring AM/PM, you can use hh in the pattern given above and then you will get 2020-10-06T11:20:00Z (but I do not recommend it as it will be confusing for anyone).
I'm converting a date string to millis like this
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
private static final DateTimeZone PST = DateTimeZone.forID("PST8PDT");
private static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormat.forPattern("yyyy-MM-dd").withZone(PST);
Long millis = DateTime.parse(startDate, DATE_FORMATTER).withTimeAtStartOfDay().getMillis());
where startDate is the date I want to convert.
How do I reverse engineer this to get the date in PST when I have the millis ?
If I understand your question you could use DateTimeFormatter.print(long),
DateTimeFormatter shortFormat =
DateTimeFormat.forPattern("MM/dd/yy").withZone(PST);
String formatted = shortFormat.print(millis);
From the linked Javadoc,
Prints a millisecond instant to a String.
I created 2 methods that is flexible enough, to handle any date Format on any timezone.
First Method is from date String to Millis (Epoch)
//dateString to long
private static long formatterDateToMillis(String dateString, String format, String timeZone){
//define Timezone, in your case you hardcoded "PST8PDT" for PST
DateTimeZone yourTimeZone = DateTimeZone.forID(timeZone);
//define your pattern
DateTimeFormatter customFormat = DateTimeFormat.forPattern(format).withZone(yourTimeZone);
//parse dateString to the format you wanted
DateTime dateTime = customFormat.parseDateTime(dateString);
//return in Millis, usually in epoch
return dateTime.getMillis();
}
Second Method is from Millis to Date String
//dateInMillis to date format yyyy-MM-dd
private static String formatterMillistoDate(long dateInMillis, String format, String timeZone){
//define your format
DateTimeFormatter customFormat = DateTimeFormat.forPattern(format);
//convert to DateTime with your desired TimeZone
DateTime dateTime = new DateTime(dateInMillis, DateTimeZone.forID(timeZone));
//return date String in format you defined
return customFormat.print(dateTime);
}
Try these inputs for your main() method:
long valueInMillis = formatterDateToMillis("2015-03-17","yyyy-MM-dd","PST8PDT");
System.out.println(valueInMillis);
String formattedInDate = formatterMillistoDate(1426575600000L,"yyyy-MM-dd","PST8PDT");
System.out.println(formattedInDate);
You should get the following output:
1426575600000
2015-03-17
Hope this helps! ;)
A Java 8 solution using java.time api which will convert a given string to millisecond and millisecond to string date considering Time Zone:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class SO25788709 {
public static void main(String[] args) {
String strDate = "2014-09-12 23:59:59";
String pattern = "yyyy-MM-dd HH:mm:ss";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
ZoneId zone = ZoneId.of("America/Los_Angeles");
long milli = getMillis(strDate, formatter, zone);
System.out.println(milli);
String retStrDate = getDateString(milli, formatter, zone);
System.out.println(retStrDate);
}
private static long getMillis(String strDate, DateTimeFormatter formatter, ZoneId zone) {
LocalDateTime localDateTime = LocalDateTime.parse(strDate, formatter);
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zone);
Instant instant = zonedDateTime.toInstant();
long milli = instant.toEpochMilli();
return milli;
}
private static String getDateString(long milli, DateTimeFormatter formatter, ZoneId zone) {
Instant instant = Instant.ofEpochMilli(milli);
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, zone);
String strDate = zonedDateTime.format(formatter);
return strDate;
}
}
Simply constructing a new DateTime object should work.
DateTime newDate = new DateTime(millis);
Overloaded with timezone