Search code examples
javakotlinzoneddatetime

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


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

Solution

  • 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.