I have the following date value 1995-12-31T23:59:59
but in order to parse this for a solr query I need it in the below format
1995-12-31T23:59:59Z
How can I parse this to get the added "Z" on the end in java 1.6 ?
The type must be java.util.date after the conversion - fyi
When I toString the date now and attempt to parse it with the SimpleDateFormat object it looks like this
"Mon Jan 01 00:00:00 CST 2001" - what is this format to convert it?
Use SimpleDateFormat:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
Date d = df.parse("1995-12-31T23:59:59Z");
System.out.println(d);
Put the 'Z' in single quotes to escape
"Z" is the time zone abbreviation for Zulu time zone i.e. UTC. If solr API accepts the date object, then you can just parse the date in the following way by setting preferred timezone:
SimpleDateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
dateParser.setTimeZone(TimeZone.getTimeZone("Z"));
Date date = df.parse("1995-12-31T23:59:59");
If you need to convert it back to string then use the method provided by nsfyn55:
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
System.out.println(dateFormatter.format());
Avoid Old Date-Time Classes
You are using the old java.util.Date/.Calendar and SimpleDateFormat classes. Avoid them.
The Date class has the poor design choice of its toString applying a default time zone when generating a String. So it seems like it has a time zone when in fact it does not (except one buried underneath that is ignored for regular use). Confusing, yes. Avoid it.
java.time
Instead use java.time built into Java 8 and later.
First parse as a LocalDateTime without any time zone or offset.
LocalDateTime ldt = LocalDateTime.parse( "1995-12-31T23:59:59Z" );
Apply a time zone or offset-from-UTC to give this LocalDateTime meaning, to make it an actual moment on the timeline. You have to know, or ask, what time zone or offset was intended by this string as no indication was embedded. For this example, I will arbitrarily assume Québec.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId );
Your desired output has a Z on the end, for Zulu which means UTC.
In java.time an Instant represents a moment on the timeline in UTC. You can extract an Instant from the ZonedDateTime.
Instant instant = zdt.toInstant();
The Instant class’ toString method generates a string in your desired format. That format is one of the standard ISO 8601 formats.
String output = instant.toString();
Half-Open
I happened to notice that your example value was trying to get the end of 1995. There is a better way to do such search or comparison criteria.
In date-time work, the best practice is called Half-Open where the beginning of a span of time is inclusive while the ending is exclusive. So a week starts on Monday and runs up to, but not including, the next Monday.
Defining a year means starting at the first moment of the first day of 1995 and running up to but not including the first moment of the first day of the following year, 1996. Searching for any values within that range is done not with a BETWEEN but as: ( someEvent >= firstMomentOf1995 AND someEvent < firstMomentOf1996 ) ( not <= ).
Related
I've tried all sorts of different conversions with different Java formatters but I'm still not having any luck with something that seems simple.
I have a string that is a date/time in UTC. I'm trying to convert that to another time zone. Is any one able to tell me why the below isn't working? The time zone is changing but it's not changing the right way.
Updated: (though it doesn't seem like I'm setting the time zone to UTC properly as the conversion isn't correct either).
String dateInput = "2021-02-16 20:57:43";
SimpleDateFormat mdyUtc = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
mdyUtc.setTimeZone(TimeZone.getTimeZone("UTC");
Date utcOutput = mdyUtc.parse(dateInput);
SimpleDateFormat mdyOffset = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
mdyOffset.setTimeZone(TimeZone.getTimeZone("GMT-10:00");
Date localOutput = mdyOffset.parse(dateInput);
System.out.print("UTC date = " + utcOutput);
System.out.print("Changed date = " + localOutput);
Output:
UTC date = Tue Feb 16 15:57:43 EST 2021
Changed date = Wed Feb 17 01:57:43 EST 2021
java.time
The java.util date-time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API*.
Using the modern date-time API:
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String dateInput = "2021-02-16 20:57:43";
// Replace ZoneId.systemDefault() with ZoneOffset.UTC if this date-time is in UTC
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH)
.withZone(ZoneId.systemDefault());
ZonedDateTime zdt = ZonedDateTime.parse(dateInput, dtf);
ZonedDateTime result = zdt.withZoneSameInstant(ZoneId.of("GMT-10:00"));
System.out.println(result);
}
}
Output:
2021-02-16T10:57:43-10:00[GMT-10:00]
ONLINE DEMO
Learn more about the modern date-time API from Trail: Date Time.
Can I get java.util.Date from ZonedDateTime?
If at all you need to use java.util.Date, you can convert ZonedDateTime into it as follows:
Date date = Date.from(result.toInstant());
Note that the java.util.Date object is not a real date-time object like the modern date-time types; rather, it represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). When you print an object of java.util.Date, its toString method returns the date-time in the JVM's timezone, calculated from this milliseconds value. If you need to print the date-time in a different timezone, you will need to set the timezone to SimpleDateFormat and obtain the formatted string from it.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. 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 and How to use ThreeTenABP in Android Project.
tl;dr
LocalDateTime // Represent a date with time-of-day but lacking the context of a time zone or offset-from-UTC.
.parse( // Interpret some text in order to build a date-time object.
"2021-02-16 20:57:43".replace( " " , "T" ) // Convert to standard ISO 8601 string to parse by default without needing to specify a formatting pattern.
) // Returns a `LocalDateTime` object.
.atOffset( // Place that date with time into the context of an offset. Determines a moment, a specific point on the timeline.
ZoneOffset.UTC // A constant for an offset of zero hours-minutes-seconds.
) // Returns an `OffsetDateTime` object.
.atZoneSameInstant( // Adjust the view of this moment as seen in the wall-clock time of some other time zone. Still the same moment, same point on the timeline.
ZoneId.of( "Pacific/Honolulu" ) // Use a time zone, if known, rather than a mere offset.
) // Returns a `ZonedDateTime` object.
.toString() // Generate text representing this moment in standard ISO 8601 format extended to append the time zone name in square brackets.
See this code run live at IdeOne.com.
2021-02-16T10:57:43-10:00[Pacific/Honolulu]
Details
The Answer by Avinash is correct, using a DateTimeFormatter with an assigned ZoneId. That works, but I prefer keeping the zone assignment separate from the formatter, to be more explicit to someone reading the code. This is only about my preference, not about correctness; both Answers are equally correct.
Parse your input as a LocalDateTime, as the input represents a date with time-of-day but lacks any indication of offset or time zone.
By default, the java.time classes use standard text formats defined in ISO 8601. If an input complies, no need to specify a formatting pattern. To comply, replace your input’s SPACE character in the middle with a T.
String input = "2021-02-16 20:57:43".replace( " " , "T" ) ;
LocalDateTime ldt = LocalDateTime.parse( input ) ;
You said you know for certain that input was meant to represent a date with time as seen in UTC, having an offset-from-UTC of zero hours-minutes-seconds. So we can apply an offset of zero using ZoneOffset to produce a OffsetDateTime.
Also, I suggest you educate the publisher of your data feed about using ISO 8601 formats to communicate that offset-of-zero fact by appending a Z (as well as using T in the middle).
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ; // Place date with time into context of an offset of zero.
Lastly, you said you want to adjust that moment to another time zone. Apply a ZoneId to get a ZonedDateTime object.
Actually, you specified an offset of "GMT-10:00". But it is better to use a time zone if known rather than a mere offset. A time zone is a history of past, present, and future changes to the offset used by the people of a particular region.
I will guess you want Hawaii time, Pacific/Honolulu.
ZoneId z = ZoneId.of( "Pacific/Honolulu" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
The java.util.Date API is deprecated; you should look into the new Date and Time APIs around LocalTime et al.
That said, if you want to keep the old code: It is a bit brittle. Your initial date input does not specify a time zone, so you'll probably get the system's time zone. You should specify a time zone --- if the expected input is UTC, say so.
Then you need to specify the time zone either in an hour offset or with a name, not both.
When I change your code to use
mdyOffset.setTimeZone(TimeZone.getTimeZone("-10:00"));
I get
Changed date = Tue Feb 16 14:57:43 CST 2021
which seems to fit, as I'm on CST (currently 6 hours after GMT), so 20:57:43 minus 6 is 14:57:43. Again, this is displayed in my local time zone. You may have to use a DateFormat to adjust the output as needed.
I have a Date field in my class that can has two types of values: with and without time. Something like this: 2015-01-01 and 2015-01-01 12:00:00. I want to make formatted string from my date. I know I can use SimpleDateFormat class for doing this, but I don't know the format. In fact, If my date has the time part, I must use yyyy-MM-dd HH:mm:ss format and if my date does not have the time part, I must use yyyy-MM-dd format. My question is, Is there anyway to check a date has time section before formatting it?
Here is my code:
private SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
.....
private String formatDate(Date date){
//I need to something like this:
if(/* `date` has time part */){
return dateTimeFormat.format(date);
}
else{
return dateFormat.format(date);
}
}
You cannot reliably do that, because once you create a Date object, it is represented as a number in milliseconds, which includes the specific time. For this reason you cannot possibly know how the object was built and if the specific time was set.
A workaround would be to check if the hours, minutes and seconds are set to zero. Keep in mind that there is a small probability that the date was parsed as "yyyy-MM-dd HH:mm:ss", but all these values were set to 0, simply because the time was indeed 00:00:00. However, this probability is equal to 1 / (24 * 60 * 60) = 0.00001157407, so I assume that you can live with that.
A Big Mess
As shown in the other answers, the old date-time classes bundled with Java such as java.util.Date and java.sql.Date are a mess. They were rushed to market, with bad design decisions. Specifically a java.util.Date represents both a date and a time-of-day, while its subclass java.sql.Date pretends not to have a time-of-day but actually does. The doc explains that you are supposed to ignore this inheritance relationship to help maintain the illusion. Not good.
java.time
This whole mess has been supplanted by the java.time framework built into Java 8 and later. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.
Date-Only
Among the new classes is LocalDate. This is the first class bundled with Java for representing a date only, without time-of-day nor time zone. To determine a date such as "today", you need a time zone (a ZoneId). For example, a new day dawns earlier in Paris than in Montréal. When you need a date-only value, I suggest you add a member to your class of this type.
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
Date-Time
If you want a date-time, first consider the Instant class. This marks a moment on the timeline in UTC. Almost always best to do your business logic and data storage in UTC. When you need a specific moment in time rather than a vague date, add a member of this type to your class.
Instant now = Instant.now();
For presentation to the user in their desired/expected time zone, apply a time zone to an Instant to get a ZonedDateTime.
ZonedDateTime zdt = ZonedDateTime.ofInstant( now , ZoneId.of( "America/Montreal" ) );
First Moment Of The Day
I do not recommend this strategy, but to directly answer your Question about detecting if the time-of-day in a date-time value happens to be the first moment of the day…
First you need to think about time zone. All of these date-time classes mentioned above track time by a count-from-epoch in UTC. The old classes count in milliseconds, the new in nanoseconds. The epoch for both old and new is the first moment of 1970 in UTC. So there is no such thing as a date-time without a time, as you pose it in the Question. The closest thing to that is a date-time whose time-of-day happens to be the first moment of the day. Seems to be your situation (though my discussion above strongly recommends you change your situation).
How to determine if a date-time has a time-of-day that is the first moment of the day? First you must consider time zone. Either you want UTC or you want a particular time zone such as America/Montreal. Depends on your business rules.
If starting with a java.util.Date, first convert to java.time.
Instant instant = myJUDate.toInstant();
Be aware that a date does not always start at the time 00:00:00.0. Because of Daylight Saving Time (DST), and possibly other anomalies, in some places the first moment of the date is a different wall-clock time. The java.time framework can determine this first moment of the day by using the LocalDate class and its atStartOfDay methods.
So after determining the time zone we care about, we adjust our Instant into a ZonedTimeZone.
Instant instant = Instant.now ();
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );
Next we need to see if that is first moment of the day. So we convert to a LocalDate, then back to another ZonedDateTime by calling atStartOfDay. Comparing the first ZonedDateTime to the second tells us if the original was indeed at the start of the day. To sum it up: We are converting from ZonedDateTime → LocalDate → ZonedDateTime.
// Convert to LocalDate, to get start of day, to compare to above.
LocalDate localDate = zdt.toLocalDate ();
ZonedDateTime startOfDay = localDate.atStartOfDay ( zoneId );
Boolean isStartOfDay = ( zdt.isEqual ( startOfDay ) );
Dump to console.
System.out.println ( "instant: " + instant + " for zoneId: " + zoneId + " is zdt: " + zdt + " if compared to startOfDay: " + startOfDay + " is T/F: " + isStartOfDay );
instant: 2015-12-12T23:20:23.560Z for zoneId: America/Montreal is zdt: 2015-12-12T18:20:23.560-05:00[America/Montreal] if compared to startOfDay: 2015-12-12T00:00-05:00[America/Montreal] is T/F: false
If you want UTC rather than a particular time zone, in the code above use the constant ZoneOffset.UTC as your ZoneId object. ZoneOffset is a subclass of ZoneId.
Assuming you're using java.sql.Date which derives from java.util.Date there is no possibility of a Date object not having a time value.
Note the documentation:
http://docs.oracle.com/javase/7/docs/api/java/sql/Date.html
A Date object instance holds a miliseconds value, to be precise the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC.
Use a Calendar object. The calendar can give you structured access to all fields of a Date value, i.e. year, month, day, hours, minutes, seconds, etc. This would allow you to check whether the time fields are non-zero. As JB Nizet stated, the time part can happen to be zero, in which case wou would misinterpret it as a date only value.
When entering the brazilian DST time period, the clocks are forward 1 hour. In 2014, DST began at 19/10, so the time 19/10/2014 00:00:00 became 19/10/2015 at 01:00:00. The period between "does not exist".
Because of this, when parsing the date "19/10/2014 00:45:00" using the timezone America/Sao_Paulo, it's thrown a parsing exception: java.text.ParseException: Unparseable date: "19/10/2014 00:45:00".
String date = "19/10/2014 00:59:00";
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
sdf.setLenient(false);
sdf.setTimeZone("America/Sao_Paulo");
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("America/Sao_Paulo"));
calendar.setTime(sdf.parse(date));
America/Sao_Paulo timezone supposedly supports DST changes. What is the expected fix for this problem? I must change manually the jvm timezone when the DST period starts and ends? Currently the "fix" is changing the jvm timezone to GMT-2 when the DST period starts.
Note: This issue originated in an application developed with spring. The example date was throwing exception when it was being converted to a java.util.Calendar from a String. In the example code above, I set lenient to false in order to be able to reproduce the error.
java.util.Calendar represents an instant in time. That instant has to exist. When local time values fall into a spring-forward DST gap, those values have no representation as a real instant in time. In other words, a properly configured clock in Brazil will never show 00:45:00 on 19/10/2014. Thus the exception. See the DST tag wiki for a visual representation.
Since you are parsing user input, I recommend parsing the string to a LocalDateTime instead of a Calendar. For Java 7, you can get this from Joda-Time. For Java 8, this is built in to the new java.time package.
Once you have it as a LocalDateTime, then you can decide where to go from there. If the time is invalid (falling into the gap of the spring-forward transition), or ambiguous (due to the fall-back transition), you can detect these scenarios and decide how to handle them in your application.
tl;dr
Use java.time to adjust from 00:45 to 01:45 in accounting for the DST cutover.
LocalDateTime.parse(
"19/10/2014 00:45:00" ,
DateTimeFormatter.ofPattern( "dd/MM/uuuu HH:mm:ss" ) // Returns a `DateTimeFormatter` object.
) // Returns a `LocalDateTime` object.
.atZone(
ZoneId.of( "America/Sao_Paulo" ) // Returns a `ZoneId` object.
) // Returns a `ZonedDateTime` object.
.toString() // Returns a `String` object holding text in standard ISO 8601 format extended to append the name of the time zone in square brackets.
2014-10-19T01:45-02:00[America/Sao_Paulo]
java.time
The modern approach uses the java.time classes that years ago supplanted the terrible date-time classes that are now legacy.
Your input string lacks an indicator of time zone or offset-from-UTC. So parse as a LocalDateTime.
String input = "19/10/2014 00:45:00";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu HH:mm:ss" );
LocalDateTime ldt = LocalDateTime.parse( input , f );
A LocalDateTime is just a date with time-of-day. So this class cannot represent a moment, is not a point on the timeline. To determine a moment, we must place the LocalDateTime in the context of a time zone, thereby producing a ZonedDateTime object.
ZoneId z = ZoneId.of( "America/Sao_Paulo" );
ZonedDateTime zdt = ldt.atZone( z );
Dump to console.
System.out.println( "ldt = " + ldt );
System.out.println( "zdt = " + zdt );
When run.
ldt = 2014-10-19T00:45
zdt = 2014-10-19T01:45-02:00[America/Sao_Paulo]
We can see that java.time made the necessary adjustment. The time-of-day of 00:45 was changed to 01:45.
Be sure to understand the logic used by java.time in this adjustment. Study the Javadoc. Only you can decide if such an adjustment is the right thing to do for your business logic.
Is date originated from user input or stored information? Note that setting GMT-3 to JVM is not the same as "America/Sao_Paulo". I don't believe GMT observes daylight saving times. Switching JVM setting back and forth doesn't look like a good solution. If it's just stored information you could update the value 1 hour ahead ou backwards, not sure which is the case here. Setting GMT-3 timezone was the only explanation I see for ending up having an invalid date in America/Sao_Paulo timezone.
I am using Java 7 and I need to display the time part of a Java Date object.
I notice that DateFormat has the SHORT constant according to the page and the page has the following description:
SHORT is completely numeric, such as 12.13.52 or 3:30pm
My question is how to display only the time part (such as "3:30pm"). The following is what I have and it only shows the date part (such as 2/14/15):
DateFormat f = DateFormat.getDateInstance(DateFormat.SHORT, A_Locale_object);
SimpleDateFormat sf = (SimpleDateFormat) f;
sf.format(new Date());
If what you want to display is the time part, what ou need to call is getTimeInstance(), and not getDateInstance().
This is the kind of answer that you should learn to find by yourself, simply by reading the javadoc:
Use getDateInstance to get the normal date format for that country. There are other static factory methods available. Use getTimeInstance to get the time format for that country. Use getDateTimeInstance to get a date and time format.
So If you want to display the time part, what you can do is provide the format to SimpleDatFormat and your locale like below
SimpleDateFormat sf = new SimpleDateFormat("hh:mm a", your_locale);
And format it like you did
sd.format(new Date()));
If you want more stuff to be formatted, you can definitely add more like "YY.MM.dd hh:mm a"
You can read the SimpleDateFormat document for more info http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
Time Zone
The Question and other Answers neglect the crucial issue of time zone. If not specified, the JVM’s current default time zone is automatically applied.
Joda-Time
Such work is easier with the Joda-Time library.
Example using Joda-Time 2.7.
Translate the java.util.Date object to a Joda-Time DateTime object. Unlike a Date, a DateTime understands its assigned time zone. We want to adjust from the Date object’s UTC zone to a desired zone such as Montréal.
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" ) ;
DateTime dateTime = new DateTime( yourDate, zone ) ;
Generate a String representation of this date-time value. A pair of characters passed to forStyle control the full, long, short etc. format of the date portion and the time portion. A hyphen suppresses display of that portion.
DateTimeFormatter formatter = DateTimeFormat.forStyle( "-S" ).withLocale( Locale.CANADA_FRENCH ) ;
String output = formatter.print( dateTime ) ;
Use getTimeInstance instead of getDateInstance.
DateFormat f = DateFormat.getTimeInstance(DateFormat.SHORT,Locale.getDefault());
I have 2 Strings
2012-06-25 15:02:22.948
+0530
I need a new string which adds the 5:30 to the time in the first string.
I thought I can do this by converting both strings to date objects and then adding. But i dont know how to do it, as when i use
yyyy MM dd hh:mm:ss as the date format for the first string, I get an error.
Thanks!
The format of the string 2012-06-25 15:02:22.948 is not yyyy MM dd hh:mm:ss, so it's not surprising that you get "an error" (what error is it? the more specific you are, the better people can help you!).
Try yyyy-MM-dd HH:mm:ss.SSS. See the API documentation of SimpleDateFormat to understand the exact syntax of the format string.
Note: Upper and lower case is important in the format string. hh means 12-hour clock, HH means 24-hour clock. If you use hh, parsing 15 for the hours won't work. You also didn't include the milliseconds SSS in the format string.
You can merge both you string String1+string2 and can use format yyyy-MM-dd HH:mm:ss.SSSZ to parse the date. You can see more documentation here
You're getting an exception because the your date format String is wrong. You're giving a date string on the form
"yyyy-MM-dd hh:mm:ss.S"
See SimpleDateFormat javadoc
Try this:
DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
Date date = format.parse("2012-06-25 15:02:22.948");
Calendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(date.getTime());
int time = Integer.parseInt("0530");
int hour = time / 100;
int minute = time % 100;
calendar.add(Calendar.HOUR_OF_DAY, hour);
calendar.add(Calendar.MINUTE, minute);
String newDateInString = format.format(calendar.getTime());
The other answers are correct but outdated.
java.time
The old date-time classes (java.util.Date/.Calendar etc.) bundled with the earliest versions of Java are now legacy.
Those old classes have been supplanted by the java.time package. See Oracle Tutorial. Much of the functionality has been back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
LocalDateTime
The LocalDateTime class represent a date-time without time zone. Use those for the first piece.
Your format is close to standard ISO 8601 format, just replace the SPACE with a T.
String input = "2012-06-25 15:02:22.948";
String inputStandardized = input.replace( " " , "T" );
LocalDateTime ldt = LocalDateTime.parse( inputStandardized );
Offset from UTC
The other piece is the offset-from-UTC. We use the ZoneOffset class for this.
ZoneOffset offset = ZoneOffset.of( "+0530" );
Without an offset or time zone the LocalDateTime is not an actual moment on the timeline but rather a rough idea about a possible moment. Now we add your offset-from-UTC to mark an actual moment, represented by the OffsetDateTime class.
OffsetDateTime odt = OffsetDateTime.of( ldt , offset );
Zoned
A time zone is an offset plus rules for handling anomalies such as Daylight Saving Time (DST). So better to use a time zone than a mere offset.
For example, if the context of this data is known to be time in India, use a time zone such as Asia/Kolkata to get a ZonedDateTime.
ZoneId zoneId = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = odt.atZoneSameInstant( zoneId );