I’ll take the big step back and suggest other and probably better ways to do your things. I don’t know your big picture, so it may be that not all of my general suggestions apply to your situation and requirements. But I consider it likely that they do.
- Do not keep nor process dates and times as strings. Keep them as
Instant
objects. When you take string input, parse it into an Instant
. Only when you need to give string output, convert your Instant
to a ZonedDateTime
in the appropriate time zone and format it into the required string.
- Your strings are in ISO 8601 format, which is good for data interchange. ISO 8601 also allows for a GMT offset (UTC offset) in the string. I suggest that you and the systems with which you communicate exploit this possibility to reduce the risk of misunderstandings. UTC is denoted
Z
, for example, 2021-01-07T18:54:00.000Z
. Other offsets are typically given in +HH:MM
format, for example 2021-01-08T00:24:00.000+05:30
or 2021-01-07T06:54:00.000-12:00
.
- Distinguish between a time zone and an offset from UTC or GMT. In Java terminology, a time zone is a place on earth with the historic, present and known future offsets used by the people in that place. Since offsets change during the history and will do that before we know it, for people in a time zone, use their time zone ID for conversion, not the GMT offset that you believe was right last time you checked. Specify the time zone in the region/city format, for example,
Asia/Kolkata
or Asia/Colombo
.
- Use java.time, the modern Java date and time API, for all of your date and time work. It is much nicer to work with than the old classes you used in the question and your own answer,
SimpleDateFormat
, Calendar
and TimeZone
. They were poorly designed and are long outdated. You were already on the way with DateTimeFormatter
and LocalDate
from java.time. Just go all-in.
I guessed that it was not user input because while ISO 8601 is readable by humans, for user input you would probably have got a still more user-friendly, localized format. So I am assuming that you get an ISO 8601 string in UTC from some other system. Convert to Instant
like this:
String sDate1="2021-01-05T00:00:00Z"; // The trailing Z means UTC
Instant inst = Instant.parse(sDate1);
System.out.println(inst);
Output so far is:
2021-01-05T00:00:00Z
Notice that we didn’t need to specify any formatter. Instant
parses ISO 8601 format in UTC with the trailing Z
just like that. An Instant
is a point in time independent of timezone.
On the same note, I am assuming that you need to give string output in some time zone to another system (maybe some front-end).
ZoneId zone = ZoneId.of("Asia/Colombo");
String output = inst.atZone(zone)
.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
System.out.println(output);
2021-01-05T05:30:00+05:30
Again we did not need to construct any formatter ourselves. I just used one that was built in.
Links