Kotlin/java - How to convert a date time string to Instant?
Asked Answered
P

2

5

I am trying to create an instance of Instant from date and time strings. Date is formatted like this yyyy-MM-dd. So the values could look like this:

val date = "2021-11-25"
val time = "15:20"

I am trying to make a valid instant from this 2 strings like this:

val dateTime = "${date}T${time}:00"
val instantDateTime = ZonedDateTime.parse(dateTime, 
                                          DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(defaultTimeZone)
                                         ).toInstant()

I have also tried with it:

val instantDateTime = Instant.from(DateTimeFormatter .ISO_OFFSET_DATE_TIME.withZone(defaultTimeZone).parse(dateTime))

But, that is not working, I get:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2021-11-25T15:20:00' could not be parsed at index 19
Privet answered 29/10, 2021 at 8:42 Comment(0)
O
8

You can combine the date and time strings to create a date-time string in ISO 8601 format which you can parse into LocalDateTime and then convert into Instant by using the applicable ZoneId. Note that the modern Date-Time API is based on ISO 8601 and does not require using a DateTimeFormatter object explicitly as long as the Date-Time string conforms to the ISO 8601 standards.

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

public class Main {
    public static void main(String[] args) {
        String strDate = "2021-11-25";
        String strTime = "15:20";
        String strDateTime = strDate + "T" + strTime;
        LocalDateTime ldt = LocalDateTime.parse(strDateTime);
        Instant instant = ldt.atZone(ZoneId.systemDefault()).toInstant();
        System.out.println(instant);
    }
}

Output:

2021-11-25T15:20:00Z

ONLINE DEMO

Some alternative approaches:

  1. Create the instance of LocalDateTime can be as suggested by daniu i.e. parse the date and time strings individually and create the instance of LocalDateTime using them.

Demo:

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;

public class Main {
    public static void main(String[] args) {
        String strDate = "2021-11-25";
        String strTime = "15:20";
        LocalDateTime ldt = LocalDateTime.of(LocalDate.parse(strDate), LocalTime.parse(strTime));
        Instant instant = ldt.atZone(ZoneId.systemDefault()).toInstant();
        System.out.println(instant);
    }
}

ONLINE DEMO

  1. Create the instance of ZonedDateTime using ZonedDateTime#of(LocalDate, LocalTime, ZoneId) as suggested by Ole V.V.. Another variant that you can try with this approach is by using ZonedDateTime#of(LocalDateTime, ZoneId).

Demo:

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        String strDate = "2021-11-25";
        String strTime = "15:20";
        ZonedDateTime zdt = ZonedDateTime.of(LocalDate.parse(strDate), LocalTime.parse(strTime),
                                                ZoneId.systemDefault());
        // Alternatively
        // ZonedDateTime zdt = ZonedDateTime.of(LocalDateTime.of(LocalDate.parse(strDate), LocalTime.parse(strTime)),
        //                                          ZoneId.systemDefault());
        
        Instant instant = zdt.toInstant();
        System.out.println(instant);
    }
}

ONLINE DEMO

  1. Combine the date and time strings to create a date-time string in ISO 8601 format and parse the same to ZonedDateTime using DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.systemDefault()).

Demo:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String strDate = "2021-11-25";
        String strTime = "15:20";
        DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.systemDefault());
        ZonedDateTime zdt = ZonedDateTime.parse(strDate + "T" + strTime, dtf);
        Instant instant = zdt.toInstant();
        System.out.println(instant);
    }
}

ONLINE DEMO

  1. Create an instance of LocalDateTime by parsing the date and time strings, and use the LocalDateTime#toInstant to get the required Instant.

Demo:

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;

public class Main {
    public static void main(String[] args) {
        String strDate = "2021-11-25";
        String strTime = "15:20";
        LocalDateTime ldt = LocalDateTime.of(LocalDate.parse(strDate), LocalTime.parse(strTime));
        Instant instant = ldt.toInstant(ZoneId.systemDefault().getRules().getOffset(ldt));
        System.out.println(instant);
    }
}

ONLINE DEMO

Learn more about the modern Date-Time API* from Trail: Date Time. Check this answer and this answer to learn how to use java.time API with JDBC.


* 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. Note that Android 8.0 Oreo already provides support for java.time.

Overanxious answered 29/10, 2021 at 9:2 Comment(4)
Matter of taste, but I find it cleaner to parse each item individually into a LocalDate and LocalTime respectively, then combine them by LocalDateTime.of(). This way you get around having to juggle around with the intermediate string.Backstretch
@Backstretch - This is indeed a great suggestion! Now, I have incorporated it into the answer. Thank you.Overanxious
I’m with @Backstretch here. We may even combine directly into a ZonedDateTime using the three-arg ZonedDateTime.of(LocalDate, LocalTime, ZoneId).Bickford
Correct, @OleV.V. and I've written many answers in these ways 😊. It's just that I wrote the first solution that came to my mind. I can still think of at least three more solutions but at the moment, I do not have time to write them 😊. I will add them whenever I will time to do so.Overanxious
M
0

Your date string doesn't include a timezone, so it cannot be parsed directly to a ZonedDateTime (see javadoc for ZonedDateTime#parse).

Try parsing the string to a LocalDateTime instead (using LocalDate#parse).

You can then convert the the LocalDateTimeto an Instant using LocalDateTime#toInstant or to a ZonedDateTime using LocalDateTime#atZone

Menfolk answered 29/10, 2021 at 8:49 Comment(3)
@Abra IMO my answer does indeed provide clear and sufficient information to solve the problem. Granted: it's not cut-and-paste ready, but then again the main purpose of this platform is helping people learn and understand, not providing readymade cut-and-paste solutions, right?Menfolk
@Menfolk actually my question is misleading I just need to convert string to an Instant, what is the simple way of doing that?Privet
@Privet Updated answer with information on how to produce an InstantMenfolk

© 2022 - 2024 — McMap. All rights reserved.