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
Related
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 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();
I have following piece of code:
String dateInString = "2016-09-18T12:17:21:000Z";
Instant instant = Instant.parse(dateInString);
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Europe/Kiev"));
System.out.println(zonedDateTime);
It gives me following exception:
Exception in thread "main" java.time.format.DateTimeParseException:
Text '2016-09-18T12:17:21:000Z' could not be parsed at index 19 at
java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
at
java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
at java.time.Instant.parse(Instant.java:395) at
core.domain.converters.TestDateTime.main(TestDateTime.java:10)
When I change that last colon to a full stop:
String dateInString = "2016-09-18T12:17:21.000Z";
โฆthen execution goes fine:
2016-09-18T15:17:21+03:00[Europe/Kiev]
So, the question is - how to parse date with Instant and DateTimeFormatter?
The "problem" is the colon before milliseconds, which is non-standard (standard is a decimal point).
To make it work, you must build a custom DateTimeFormatter for your custom format:
String dateInString = "2016-09-18T12:17:21:000Z";
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_DATE_TIME)
.appendLiteral(':')
.appendFraction(ChronoField.MILLI_OF_SECOND, 3, 3, false)
.appendLiteral('Z')
.toFormatter();
LocalDateTime instant = LocalDateTime.parse(dateInString, formatter);
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Europe/Kiev"));
System.out.println(zonedDateTime);
Output of this code:
2016-09-18T12:17:21+03:00[Europe/Kiev]
If your datetime literal had a dot instead of the last colon, things would be much simpler.
Use a SimpleDateFormat:
String dateInString = "2016-09-18T12:17:21:000Z";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss:SSS");
Instant instant = sdf.parse(dateInString).toInstant();
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Europe/Kiev"));
System.out.println(zonedDateTime);
2016-09-18T19:17:21+03:00[Europe/Kiev]
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/MM/yyyy");
String date = "16/08/2016";
//convert String to LocalDate
LocalDate localDate = LocalDate.parse(date, formatter);
If the String is formatted like ISO_LOCAL_DATE, you can parse the String directly, no need conversion.
package com.mkyong.java8.date;
import java.time.LocalDate;
public class TestNewDate1 {
public static void main(String[] argv) {
String date = "2016-08-16";
//default, ISO_LOCAL_DATE
LocalDate localDate = LocalDate.parse(date);
System.out.println(localDate);
}
}
Check out this site
Site here
I am using Java 8
This is what my ZonedDateTime looks like
2013-07-10T02:52:49+12:00
I get this value as
z1.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
where z1 is a ZonedDateTime.
I wanted to convert this value as 2013-07-10T14:52:49
How can I do that?
Is this what you want?
This converts your ZonedDateTime to a LocalDateTime with a given ZoneId by converting your ZonedDateTime to an Instant before.
LocalDateTime localDateTime = LocalDateTime.ofInstant(z1.toInstant(), ZoneOffset.UTC);
Or maybe you want the users system-timezone instead of hardcoded UTC:
LocalDateTime localDateTime = LocalDateTime.ofInstant(z1.toInstant(), ZoneId.systemDefault());
It looks like you need to convert to the desired time zone (UTC) before sending it to the formatter.
z1.withZoneSameInstant( ZoneId.of("UTC") )
.format( DateTimeFormatter.ISO_OFFSET_DATE_TIME )
should give you something like 2018-08-28T17:41:38.213Z
#SimMac Thanks for the clarity. I also faced the same issue and able to find the answer based on his suggestion.
public static void main(String[] args) {
try {
String dateTime = "MM/dd/yyyy HH:mm:ss";
String date = "09/17/2017 20:53:31";
Integer gmtPSTOffset = -8;
ZoneOffset offset = ZoneOffset.ofHours(gmtPSTOffset);
// String to LocalDateTime
LocalDateTime ldt = LocalDateTime.parse(date, DateTimeFormatter.ofPattern(dateTime));
// Set the generated LocalDateTime's TimeZone. In this case I set it to UTC
ZonedDateTime ldtUTC = ldt.atZone(ZoneOffset.UTC);
System.out.println("UTC time with Timezone : "+ldtUTC);
// Convert above UTC to PST. You can pass ZoneOffset or Zone for 2nd parameter
LocalDateTime ldtPST = LocalDateTime.ofInstant(ldtUTC.toInstant(), offset);
System.out.println("PST time without offset : "+ldtPST);
// If you want UTC time with timezone
ZoneId zoneId = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdtPST = ldtUTC.toLocalDateTime().atZone(zoneId);
System.out.println("PST time with Offset and TimeZone : "+zdtPST);
} catch (Exception e) {
}
}
Output:
UTC time with Timezone : 2017-09-17T20:53:31Z
PST time without offset : 2017-09-17T12:53:31
PST time with Offset and TimeZone : 2017-09-17T20:53:31-08:00[America/Los_Angeles]
If z1 is an instance of ZonedDateTime, then the expression
z1.withZoneSameInstant(ZoneOffset.UTC).toLocalDateTime()
evaluates to an instance of LocalDateTime with the string representation requested by the OP. This is illustrated by the following program:
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
public class Main {
public static void main(String[] args) {
ZonedDateTime time = ZonedDateTime.now();
ZonedDateTime truncatedTime = time.truncatedTo(ChronoUnit.SECONDS);
ZonedDateTime truncatedTimeUtc = truncatedTime.withZoneSameInstant(ZoneOffset.UTC);
LocalDateTime truncatedTimeUtcNoZone = truncatedTimeUtc.toLocalDateTime();
System.out.println(time);
System.out.println(truncatedTime);
System.out.println(truncatedTimeUtc);
System.out.println(truncatedTimeUtcNoZone);
}
}
Sample output:
2020-10-26T16:45:21.735836-03:00[America/Sao_Paulo]
2020-10-26T16:45:21-03:00[America/Sao_Paulo]
2020-10-26T19:45:21Z
2020-10-26T19:45:21
I wanted to convert this value as 2013-07-10T14:52:49
๐ 2013-07-10T02:52:49+12:00 โ 2013-07-10T14:52:49 at UTC
๐ 2013-07-10T02:52:49+12:00 = 2013-06-09T14:52:49 at UTC (which is obtained by subtracting 12:00 hours of the offset from 2013-07-10T02:52:49).
Demo:
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
class Main {
public static void main(String[] args) {
ZoneOffset zoneOffset = ZoneOffset.of("+12:00");
OffsetDateTime odtGiven = OffsetDateTime.of(LocalDateTime.of(2013, 7, 10, 2, 52, 49), zoneOffset);
System.out.println(odtGiven);
OffsetDateTime odtUtc = odtGiven.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println(odtUtc);
System.out.println(odtUtc.toLocalDateTime());
}
}
Output:
2013-07-10T02:52:49+12:00
2013-07-09T14:52:49Z
2013-07-09T14:52:49
Learn about the modern Date-Time API from Trail: Date Time.