Issue with parsing date time using ZonedDateTime and DateTimeFormatter - java

I am having two different results from these two blocks even though the input date/time to parse is the same
public class DateTimeFormatterUtilsTest
{
private static final String ISO_DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";;
private static final String ISO_DATETIME_TO_PARSE = "2007-12-03T10:15:30.000Z";
private static final long TARGET_EPOCH_TIME = 1196676930000L;
#Test
public void testDateTimeFormatterUtils()
{
ZoneId targetZoneid = TimeUtils.getZoneId(TIMEZONE.PST);
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT.withZone(targetZoneid);
long epochTime = parseDateTime(ISO_DATETIME_TO_PARSE, formatter);
assertTrue(epochTime == TARGET_EPOCH_TIME);
// specify custom pattern
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern(ISO_DATETIME_PATTERN).withZone(targetZoneid);
epochTime = parseDateTime(ISO_DATETIME_TO_PARSE, formatter1);
assertTrue(epochTime == TARGET_EPOCH_TIME);
}
public long parseDateTime(final String dateTimeString, DateTimeFormatter formatter)
{
ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateTimeString, formatter);
System.out.println("parsed zoned date time" + zonedDateTime);
Instant instant = zonedDateTime.toInstant();
long epochTime = instant.toEpochMilli();
System.out.println("Epoch time for" + ISO_DATETIME_TO_PARSE + "is " + epochTime);
return epochTime;
}
}
When I am using DateTimeFormatter.ISO_INSTANT I get the correct epoch time which is 1196676930000, however, when I am usin the .ofPattern method to create the DateTimeFormatter I am getting 1196705730000. Not sure why?
As you can see, the difference is 28 800 000 milliseconds or exactly 8 hours.

Never put quote marks around the Z in a date-time formatting pattern.
Z means +00:00
The Z is a standard abbreviation for an offset of zero. Pronounced “Zulu” per aviation/military convention.
Yuor quotes treat the Z as meaningless string literal, preventing semantic interpretation. The Z carries vital information, meaning “an offset from UTC of zero hours-minutes-seconds”. But your 'Z' parsing pattern ignores that info.
This:
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
… should be:
"yyyy-MM-dd'T'HH:mm:ss.SSSZ"
By ignoring that offset, the JVM’s current default time zone is applied implicitly when you parsed as a ZonedDateTime. Hence your correct but unexpected results.
Instant, not ZonedDateTime
Your input has no indication of time zone. So ZonedDateTime is not called for here.
Instead, parse as an Instant.
Instant.parse( "2007-12-03T10:15:30.000Z" )
If you want to see that moment through the lens of a particular time zone, apply a ZoneId to get a ZonedDateTime. Same moment, different wall-clock time.
ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Terminology
Quick review of terms:
UTC is the temporal prime meridian. In the old days this was the time kept at the Royal Observatory in Greenwich, London.
An offset is merely a number of hours-minutes-seconds ahead or behind UTC.
A time zone is a named history of the past, present, and future changes to the offset used by the people of a particular region as decided by their politicians.

Related

Compare ZoneDateTime with different time zones

Hi I've already search for similar questions but without luck.
I'm calling a ws that sends me back a token and when it's valid example:
{
"token": ...,
"notBefore":"Thu 21 Jul 2022 at 10:50:43",
"notOnOrAfter":"Thu 21 Jul 2022 at 12:50:43"
}
I know that this dates are GMT+2 (Rome), now I'm taking the current time and convert the two strings:
ZonedDateTime currentTime = LocalDateTime.now().atZone(ZoneId.of("GMT+2"));
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(token.getTimePattern(), Locale.ENGLISH);
ZonedDateTime tokenNotValidAfter = LocalDateTime.parse(token.getNotOnOrAfter(), dateTimeFormatter).atZone(ZoneId.of("GMT+2"));
ZonedDateTime tokenNotValidBefore = LocalDateTime.parse(token.getNotBefore(), dateTimeFormatter).atZone(ZoneId.of("GMT+2"));
if (!currentTime.isAfter(tokenNotValidBefore) || !currentTime.isBefore(tokenNotValidAfter)) {
throw new CifTokenExpiredException(ExceptionHandlerConfig.CIF_TOKEN_EXPIRED);
}
Now locally everthing is working fine, when i deploy on cloud i get:
ZonedDateTime currentTime = LocalDateTime.now().atZone(ZoneId.of("GMT+2"));
two hours behind.
How can i solve this without adding two hours to currentTime? (doing like this locally will not work)
Regards
GMT+2 is an offset, Middle Europe +1 hour plus 1 hour summer time.
That would go wrong in the coming winter. In fact you are using the incomplete OffsetDateTime, which without Locale is inconclusive for the real Zone.
ZonedDateTime currentTime = ZonedDateTime.now(ZoneId.of("Europe/Rome"));
As you see, no need to revert to LocalDateTime.
Now you can get currentTime.toInstant() for an absolute UTC number.
An Instant is even Comparable, but Before/After is fine.
You assume that before and after limits are also in the Italian time zone, but that may be as it is.
There are some things to consider, because of DST (summer time, daylight savings time):
With a count down ("Still 243 hours till the end") you can get awkward jumps of 1 hour per day.
Twice a year there is the 02:00-03:00 gap or repetition (Western Europe). These stati can be queried.
The answer by Joop Eggen is correct. I'll add some more complete code example.
I suggest you educate the publisher of your data on two points:
Date-time values being exchanged textually should use standard ISO 8601 format rather than inventing a localized format as seen in your case.
Moments (specific points on the timeline) should always be communicated in the context of a time zone or offset. Preferably with an offset of zero hours-minutes-seconds. This implied time zone of Rome is just asking for trouble. Or, if not a moment but a time-of-day that should remain the same even if politicians change the time zone rules, then communicate the intended time zone as another field in the date stream, in Continent/Region format such as Europe/Rome.
I suggest adding the ThreeTen-Extra library to your project. Doing so gives you the Interval class that represents a span of time attached to the timeline as a pair of Instant objects. Handy methods include contains, abuts, overlaps, and more.
String inputBegin = "Thu 21 Jul 2022 at 10:50:43";
String inputEnd = "Thu 21 Jul 2022 at 12:50:43";
Locale locale = Locale.US;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "EEE d MMM uuuu 'at' HH:mm:ss" ).withLocale( locale );
ZoneId zoneId = ZoneId.of( "Europe/Rome" ); // Assumed to be the intended time zone.
LocalDateTime beginLdt = LocalDateTime.parse( inputBegin , f );
LocalDateTime endLdt = LocalDateTime.parse( inputEnd , f );
ZonedDateTime begin = beginLdt.atZone( zoneId );
ZonedDateTime end = endLdt.atZone( zoneId );
Interval whenValid = Interval.of( begin.toInstant() , end.toInstant() );
Instant now = Instant.now();
boolean isValidNow = whenValid.contains( now );
System.out.println( begin + "/" + end );
String message = "Interval: " + whenValid + " contains now: " + now + " = " + isValidNow;
System.out.println( message );
2022-07-21T10:50:43+02:00[Europe/Rome]/2022-07-21T12:50:43+02:00[Europe/Rome]
Interval: 2022-07-21T08:50:43Z/2022-07-21T10:50:43Z contains now: 2022-07-21T21:17:54.458095Z = false
In the cloud time is always considered to be GMT. So the best action is to change ZonedDateTime currentTime = LocalDateTime.now().atZone(ZoneId.of("GMT+2"));
to
ZonedDateTime currentTime = ZonedDateTime.now()

Get the start and end timestamp of the given timestamp in java

I had a timestamp in Unix with milliseconds, now I need the start of the day and end of the day with milliseconds for the same given timestamp.
Eg: 1637293359000 - Given timestamp
Start of the day to be 1637280000000
End of the day to be 1637323199000
In System default timezone you could try like this
ZoneId zoneId = ZoneId.systemDefault();
long timestamp = 1637293359000L;
LocalDate date = Instant.ofEpochMilli(timestamp).atZone(zoneId).toLocalDate();
LocalDateTime startDay = date.atStartOfDay();
LocalDateTime endDay = date.atTime(LocalTime.MAX);
System.out.println(startDay);
System.out.println(endDay);
long startDayLongValue = startDay.atZone(zoneId).toInstant().toEpochMilli();
long endDayLongValue = endDay.atZone(zoneId).toInstant().toEpochMilli();
System.out.println(startDayLongValue);
System.out.println(endDayLongValue);
We can achieve this using DateTime
import org.joda.time.DateTime;
long timestamp = 1629454215381L;
DateTime dateTime=new DateTime(timestamp );
long StartOfDayMillis = dateTime.withMillis(System.currentTimeMillis()).withTimeAtStartOfDay().getMillis();
long EndOfDayMillis = dateTime.withMillis(StartOfDayMillis).plusDays(1).minusSeconds(1).getMillis();
tl;dr
Here is the complete code to a record representing the day of a specified moment as seen in a particular time zone. A static factory method contains our logic.
package work.basil.example;
import java.time.*;
import java.util.Objects;
public record DayInMillis( long start , long end )
{
public static DayInMillis from ( final long countOfMillisSinceEpoch , final ZoneId zoneId )
{
Objects.requireNonNull( zoneId );
Instant instant = Instant.ofEpochMilli( countOfMillisSinceEpoch );
ZonedDateTime zdt = instant.atZone( zoneId );
LocalDate ld = zdt.toLocalDate();
ZonedDateTime start = ld.atStartOfDay( zoneId );
ZonedDateTime end = ld.plusDays( 1 ).atStartOfDay( zoneId );
Instant startInstant = start.toInstant();
Instant endInstant = end.toInstant();
long startMilli = startInstant.toEpochMilli();
long endMilli = endInstant.toEpochMilli();
System.out.println( "instant = " + instant );
System.out.println( "zdt = " + zdt );
System.out.println( "start/end = " + start + "/" + end );
System.out.println( "startInstant/endInstant = " + startInstant + "/" + endInstant );
System.out.println( "startMilli/endMilli = " + startMilli + "/" + endMilli );
System.out.println( "Duration (not necessarily 24 hours): " + Duration.between( startInstant , endInstant ) );
return new DayInMillis( startMilli , endMilli );
}
}
Example usage:
DayInMillis.from( 1_637_293_359_000L , ZoneId.of( "Asia/Tokyo" ) )
When run.
instant = 2021-11-19T03:42:39Z
zdt = 2021-11-19T12:42:39+09:00[Asia/Tokyo]
start/end = 2021-11-19T00:00+09:00[Asia/Tokyo]/2021-11-20T00:00+09:00[Asia/Tokyo]
startInstant/endInstant = 2021-11-18T15:00:00Z/2021-11-19T15:00:00Z
startMilli/endMilli = 1637247600000/1637334000000
Duration (not necessarily 24 hours): PT24H
dayInMillis = DayInMillis[start=1637247600000, end=1637334000000]
Parse count of seconds
Parse your input count of milliseconds since epoch of first moment of 1970 in UTC as a Instant object.
Instant instant = Instant.ofEpochMilli( 1_637_293_359_000L ) ;
Adjust into time zone
Specify the time zone by which you want to perceive dates.
ZoneId z = ZoneId.of( "America/Edmonton" ) ;
Adjust from UTC (an offset of zero hours-minutes-seconds) to that time zone.
ZonedDateTime zdt = instant.atZone( z ) ;
Get the date
Extract the date-only portion.
LocalDate ld = zdt.toLocalDate() ;
Start of day
Let java.time determine the first moment of the day. Never assume the day starts at 00:00. Some dates in some zones may start at another time such as 01:00.
ZonedDateTime start = ld.atStartOfDay( z ) ;
Half-Open
The last moment of the day is infinitely divisible. For this and other reasons, spans of time are usually best defined using Half-Open approach. In Half-Open, the beginning is inclusive while the ending is exclusive. This means the span of a day starts at the first moment of the day and runs up to, but does not include, the first moment of the following day.
ZonedDateTime end = ld.plusDays( 1 ).atStartOfDay( z ) ;
Now we have the span covered by a pair of ZonedDateTime objects. But you want to get a count of milliseconds since epoch for both of those.
Tracking count-from-epoch is awkward
Let me say, I do not recommend using a count-since-epoch for time-keeping. The values are inherently ambiguous as to both epoch and granularity. Furthermore, using such counts makes debugging difficult and errors hard to spot, as such values are meaningless to human readers.
ISO 8601
Instead, I suggest communicating such values textually in standard ISO 8601 format. The java.time classes use ISO 8601 formats by default when parsing/generating text.
String outputStart = start.toInstant().toString();
String outputEnd = end.toInstant().toString();
Milliseconds since epoch
But if you insist on the count of milliseconds, first extract Instant objects from our ZonedDateTime objects, effectively adjusting to UTC (offset of zero).
Instant startInstant = start.toInstant() ;
Instant endInstant = end.toInstant() ;
Interrogate for a count of milliseconds since epoch.
long startMilli = startInstant.toEpochMilli() ;
long endMilli = endInstant.toEpochMilli() ;
Avoid LocalDateTime for this problem
Notice that at no point did we use the LocalDateTime class. That class purposely lacks the context of a time zone or offset-from-UTC. So LocalDateTime cannot represent a moment, is not a point on the timeline. That makes LocalDateTime irrelevant to the problem at hand.
Tip: ThreeTen-Extra library
If you routinely work with pairs of moments, considering adding the ThreeTen-Extra library to your project. This provides the Interval class for representing a pair of Instant objects. The class carries several handy comparison methods such as abuts, overlaps, contains, and so on.

How can I get UTC Instant of startDate and endDate of today in a specific time zone ("Europe/Paris")

I want to get the UTC instant (since my DB is storing in UTC) from Java (which is also in UTC) of a particular time zone, this is what I have tried so far:
public static Instant getStartOfTheDayDateTime(Instant instant, String zoneId) {
ZonedDateTime zoned = instant.atZone(ZONE_ID_TO_ZONE_MAP.get(zoneId));
ZoneId zone = ZoneId.of(zoneId);
return zoned.toLocalDate().atStartOfDay(zone).toInstant();
// ZonedDateTime startOfTheDay = zoned.withHour(0)
// .withMinute(0)
// .withSecond(0)
// .withNano(0);
//
// return startOfTheDay.toInstant();
}
public static Instant getEndOfTheDayDateTime(Instant instant, String zoneId) {
ZonedDateTime zoned = instant.atZone(ZONE_ID_TO_ZONE_MAP.get(zoneId));
ZonedDateTime endOfTheDay = zoned.withHour(0)
.withMinute(0)
.withSecond(0)
.withNano(0)
.plusDays(1);
return endOfTheDay.toInstant();
}
Every attempt shows:
2020-04-10 22:00:00.0(Timestamp), 2020-04-11 22:00:00.0(Timestamp)
Is this the start/end of the day UTC time in Europe/Paris zone ?
I was expecting to have 2020-04-11 02:00:00.0(Timestamp), 2020-04-12 02:00:00.0(Timestamp)
Right now, Paris is on summer time: UTC+2. Paris is 'ahead' of UTC by 2 hours.
So 00:00:00 in Paris local time is 22:00:00 UTC.
Is this the start/end of the day UTC time in Europe/Paris zone ?
Yes. Europe/Paris is in daylight savings time. Midnight in Paris occurred at 22:00 UTC time.
I was expecting to have 2020-04-11 02:00:00.0(Timestamp), 2020-04-12 02:00:00.0(Timestamp)
That's not right, 02:00 UTC would have been 04:00 in Paris time.
Ask programmatically if a moment is in DST
Is this the start/end of the day UTC time in Europe/Paris zone ?
Get start of day.
ZoneId z = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtStartOfDay = instant.atZone( z ).toLocalDate().atStartOfDay( z ) ;
Ask if that moment is in DST for that zone.
ZoneRules rules = z.getRules();
boolean isDst = rules.isDaylightSavings( zdtStartOfDay.toInstant() );
Pass date-time objects rather than mere strings
public static Instant getStartOfTheDayDateTime(Instant instant, String zoneId)
I suggest you ask the calling programmer to pass a valid ZoneId object rather than a mere string. It should not be the job of this method to validate their string input. If it is reasonable to expect a Instant then it is also reasonable to expect a ZoneId.
public static Instant getStartOfTheDayDateTime(Instant instant, ZoneID zoneId )
Half-Open
public static Instant getEndOfTheDayDateTime(Instant instant, String zoneId) {
Trying to determine the last moment of the day is impossible because of infinitely divisible last second.
Also this approach to defining a span of time is awkward. It makes abutting multiple spans tricky. Various software systems and protocols differ in their resolution of that last fractional second, using milliseconds, microseconds, nanoseconds, or some other fraction.
The common practice in date-time handling is to track a span of time using the Half-Open approach. In Half-Open, the beginning is inclusive while the ending is exclusive.
So a full day begins with the first moment of the day and runs up to, but does not include, the first moment of the next day.
ZoneId z = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtStartOfDay = instant.atZone( z ).toLocalDate().atStartOfDay( z ) ;
ZonedDateTime zdtStartOfNextDay = instant.atZone( z ).toLocalDate().plusDays( 1 ).atStartOfDay( z ) ;
You might want to break that code out to more lines, for easier reading/debugging.
Instant instant = Instant.now() ; // Or passed in.
ZoneId z = ZoneId.of( "Europe/Paris" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
LocalDate ld = zdt.toLocalDate() ;
LocalDate ldNextDay = ld.plusDays( 1 ) ;
ZonedDateTime zdtStartOfNextDay = ldNextDay.atStartOfDay( z ) ;
See this code run live at IdeOne.com. For example:
System.out.println( instant ) ; // 2020-04-13T00:15:25.235341Z
System.out.println( zdt ) ; // 2020-04-13T02:15:25.235341+02:00[Europe/Paris]
System.out.println( ld ) ; // 2020-04-13
System.out.println( ldNextDay ) ; // 2020-04-14
System.out.println( zdtStartOfNextDay ) ; // 2020-04-14T00:00+02:00[Europe/Paris]
ThreeTen-Extra Interval
If you do this kind of work with spans of time often, then I suggest adding the ThreeTen-Extra library to your project. That library includes the Interval class to track a span-of-time as a a pair of Instant objects.
Interval interval = Interval.of( zdtStartOfDay.toInstant() , zdtStartOfNextDay.toInstant() ) ;
You can then make use the several handy comparison methods such as abuts, contains, encloses, intersection, overlaps, and union.
Timestamp
Never use the java.sql.Timestamp class. This class is part of the terrible date-time classes that shipped with the earliest versions of Java. These classes are now legacy, supplanted entirely by the modern java.time classes defined in JSR 310 and built into Java 8 and later.
As of JDBC 4.2 we can exchange java.time objects with a database. Use getObject and setObject and updateObject.
The JDBC spec oddly requires support for OffsetDateTime but not the more commonly used Instant and ZonedDateTime. Your particular driver may support these other types. If not, convert.
Retrieval from database.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;
Sending to the database.
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;

Plus 1 hour and 1 day in date using java 8 apis

I have this code to add 1 hour or 1 day in date Java 8, but doesn´t work
String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
java.text.SimpleDateFormat format = new java.text.SimpleDateFormat(DATE_FORMAT);
Date parse = format.parse("2017-01-01 13:00:00");
LocalDateTime ldt = LocalDateTime.ofInstant(parse.toInstant(), ZoneId.systemDefault());
ldt.plusHours(1);
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date te = Date.from(zdt.toInstant());
What´s wrong? The code shows: Sun Jan 01 13:00:00 BRST 2017
LocalDateTime is immutable and returns a new LocalDateTime when you call methods on it.
So you must call
ldt = ldt.plusHours(1);
Apart from the issue that you don't use the result of your date manipulation (ldt = ldt.plusHours(1)), you don't really need to go via a LocalDateTime for this operation.
I would simply use an OffsetDateTime since you don't care about time zones:
OffsetDateTime odt = parse.toInstant().atOffset(ZoneOffset.UTC);
odt = odt.plusDays(1).plusHours(1);
Date te = Date.from(odt.toInstant());
You could even stick to using Instants:
Instant input = parse.toInstant();
Date te = Date.from(input.plus(1, DAYS).plus(1, HOURS));
(with an import static java.time.temporal.ChronoUnit.*;)
tl;dr
LocalDateTime.parse( // Parse input string that lacks any indication of offset-from-UTC or time zone.
"2017-01-01 13:00:00".replace( " " , "T" ) // Convert to ISO 8601 standard format.
).atZone( // Assign a time zone to render a meaningful ZonedDateTime object, an actual point on the timeline.
ZoneId.systemDefault() // The Question uses default time zone. Beware that default can change at any moment during runtime. Better to specify an expected/desired time zone generally.
).plus(
Duration.ofDays( 1L ).plusHours( 1L ) // Add a span of time.
)
Details
Do not mix the troublesome old legacy classes Date and Calendar with the modern java.time classes. Use only java.time, avoiding the legacy classes.
The java.time classes use the ISO 8601 standard formats by default when parsing and generating strings. Convert your input string by replacing the SPACE in the middle with a T.
String input = "2017-01-01 13:00:00".replace( " " , "T" ) ;
LocalDateTime ldt = LocalDateTime.parse( input ) ;
ALocalDateTime does not represent an actual moment, not a point on the timeline. It has no real meaning until you assign a time zone.
ZoneId z = ZoneId.systemDefault() ; // I recommend specifying the desired/expected zone rather than relying on current default.
ZonedDateTime zdt = ldt.atZone( z ) ;
A Duration represents a span of time not attached to the timeline.
Duration d = Duration.ofDays( 1L ).plusHours( 1L ) ;
ZonedDateTime zdtLater = zdt.plus( d ) ;

Get Time stamp using Java GMT+5:30

I want Timestamp of given date.
using this code
public static String getTimestamp(String time)
{
DateFormat dfm = new SimpleDateFormat("dd-mm-yy hh:mm:ss");
long unixtime = 0;
dfm.setTimeZone(TimeZone.getTimeZone("GMT+5:30"));
try
{
unixtime = dfm.parse(time).getTime();
unixtime=unixtime/1000;
}
catch (ParseException e)
{
e.printStackTrace();
}
return ""+unixtime;
}
public static void main(String[] args)
{
System.out.println(getTimestamp("11-05-15 11:54:55"));
}
but when i enter this date 11-05-15 11:54:55 then program return me 1420957495 this timestamp which is timestamp of Jan (01) but i want May(06)
please help me
use this
DateFormat dfm = new SimpleDateFormat("dd-MM-yy hh:mm:ss");
Upper case MM is for month and lower case is for minute
Your Offset Is Invalid
A valid offset must include padded zero. Your offset string GMT+5:30 should be GMT+05:30 with a 0 before the 5.
Beyond that, the Answer by Meno Hochschild is correct and wise.
java.time
The java.util.Date/.Calendar and SimpleDateFormat classes are notoriously troublesome, confusing, and flawed. Avoid them.
Instead use java.time package found in Java 8 and later. Where lacking, use the Joda-Time library.
Here is some java.time code (Java 8).
First, parse your input into a "local" date-time value, meaning without any time zone attached. As there was no offset nor time zone included with the input, this value could apply to any particular locality.
String input = "11-05-15 11:54:55"; // Strongly recommend using 4-digit year whenever possible, as suggested in Meno Hochschild’s Answer.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "dd-MM-yy HH:mm:ss" ); // No need for Locale in this case, but always consider it.
LocalDateTime localDateTime = LocalDateTime.parse( input , formatter );
Next, we are presuming this value was meant to represent a moment in India. Let’s assign a time zone. We could assign merely an offset. But generally we should use a time zone. A time zone is an offset plus the past, present, and future set of rules for adjustments and anomalies such as Daylight Saving Time.
First we instantiate a time zone for India. Then we generate a ZonedDateTime based on the LocalDateTime while adding a time zone.
// Assign a time zone.
//ZoneId zoneId_plus_5_30 = ZoneId.of( "GMT+05:30" ); // You can use an offset, but know that a time zone is *more* than an offset.
ZoneId zoneIdKolkata = ZoneId.of( "Asia/Kolkata" ); // Better to use a time zone name if one is applicable. Ex: "Asia/Kolkata".
ZonedDateTime zonedDateTimeKolkata = ZonedDateTime.of( localDateTime , zoneIdKolkata );
For fun, let’s adjust the same moment to UTC and to Montréal.
ZonedDateTime zonedDateTimeUtc = zonedDateTimeKolkata.withZoneSameInstant( ZoneOffset.UTC );
ZonedDateTime zonedDateTimeMontréal = zonedDateTimeKolkata.withZoneSameInstant( ZoneId.of( "America/Montreal" ) );
Dump to console.
System.out.println( "Input: " + input );
System.out.println( "localDateTime: " + localDateTime );
System.out.println( "zonedDateTimeKolkata: " + zonedDateTimeKolkata );
System.out.println( "zonedDateTimeUtc: " + zonedDateTimeUtc );
System.out.println( "zonedDateTimeMontréal: " + zonedDateTimeMontréal );
When run.
Input: 11-05-15 11:54:55
localDateTime: 2015-05-11T11:54:55
zonedDateTimeKolkata: 2015-05-11T11:54:55+05:30[Asia/Kolkata]
zonedDateTimeUtc: 2015-05-11T06:24:55Z
zonedDateTimeMontréal: 2015-05-11T02:24:55-04:00[America/Montreal]
You should change your pattern. So far the accepted answer is right with respect to month. What is still missing is the pattern symbol for the hour of day. It should be H instead of h. Or if you prefer the English hour notation, you can use an additional letter "a" indicating AM/PM. So the final solution is:
DateFormat dfm = new SimpleDateFormat("dd-MM-yy HH:mm:ss");
or
DateFormat dfm = new SimpleDateFormat("dd-MM-yy hh:mm:ss a", Locale.ENGLISH);
And I recommend to use 4-digit-years to exclude any ambivalence using yyyy, by the way.

Categories

Resources