The Answer by Godfrey is correct.
tl;dr
LocalDate.parse(
"04/05/2018" ,
DateTimeFormatter.ofPattern( "MM/dd/uuuu" )
)
.atStartOfDay(
ZoneId.of( "Asia/Kolkata" )
)
.toString()
2018-04-05T00:00+05:30[Asia/Kolkata]
For storage in your database, use UTC.
When a new day starts in India, the date at UTC is still “yesterday”, so April 4th rather than April 5th. Same moment, same point on the timeline, different wall-clock time.
LocalDate.parse(
"04/05/2018" ,
DateTimeFormatter.ofPattern( "MM/dd/uuuu" )
)
.atStartOfDay(
ZoneId.of( "Asia/Kolkata" )
)
.toInstant()
2018-04-04T18:30:00Z
java.time
You are using terrible old date-time classes that have proven to be poorly designed, confusing, and troublesome. They are now supplanted by the java.time classes.
Avoid legacy date-time classes entirely
ZoneOffset zoneOffset = ZoneOffset.ofTotalSeconds(-timeZoneOffset * 60);
…
TimeZone timeZone = TimeZone.getTimeZone(zoneOffset);
You are mixing the modern classes (ZoneOffset
) with the troublesome legacy classes (TimeZone
). Do not mix the modern classes with the legacy classes. Forget all about the old classes including Date
, Calendar
, and SimpleDateFormat
. The java.time classes are designed to entirely supplant the legacy classes.
Instead of TimeZone
, use ZoneId
(and ZoneOffset
).
LocalDate
Parse your input string as a LocalDate
. The LocalDate
class represents a date-only value without time-of-day and without time zone.
String input = "04/05/2018" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd/uuuu" ) ;
LocalDate ld = LocalDate.parse( input , f ) ;
Offset versus Time Zone
int timeZoneOffset = -330;
An offset-from-UTC is not a time zone. An offset is simply a number of hours, minutes, and seconds of displacement from UTC. Your choice of variable name indicates possible confusion on this point.
ZoneOffset offset = ZoneOffset.of( -3 , 30 ) ;
A time zone is a history of past, present, and future changes in offset used by the people of a particular region. So a time zone is always preferable to an offset.
Specify a proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 3-4 letter abbreviation such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ; // India time zone. Currently uses offset of +05:30 (five and a half hours ahead of UTC).
First moment of the day
You seem to be aiming for the first moment of that date in that zone. Let java.time determine that first-moment-of-the-day. Do not assume that time is 00:00:00. In some zones on some dates, the day may start at another time such as 01:00:00.
ZonedDateTime zdt = ld.atStartOfDay( z ) ; // Determine the first moment of the day on this date in this zone. Not always 00:00:00.
As an example of why you should be using time zones rather than mere offset-from-UTC, look at your example data of -330
which I might easily misinterpret to be three and a half hours behind UTC. This offset is currently only used in the zone America/St_Johns
, and only used there for part of the year. So if you applied an offset of -03:30 to a date in the wrong part of the year, your results would be invalid yet go undetected.
Using offset (not recommended)
But your example lacks time zone, so let’s go with offset-from-UTC rather than zone.
Your use of an int
integer number to represent an offset-from-UTC is a poor choice of types. First of all, it is ambiguous. That -330
might be interpreted to be a clumsy attempt at -03:30
offset of three and a half hours behind schedule. Secondly, it makes parsing trickier than need be. Thirdly, as a number of minutes, it ignores the possibility of an offset with seconds. Fourthly, you use a negative number for an offset ahead of UTC (apparently) despite common usage and standard usage being the opposite. Lastly, it ignores the clear standard set by ISO 8601 for representing offsets as text: ±HH:MM:SS
(and variations). By the way, the padding zero is optional in the standard, but I recommend always including because various libraries and protocols expect it.
Your intent appears to be a number of minutes intended by the integer number.
long seconds =( TimeUnit.MINUTES.toSeconds( - 330 ) * -1 ); // Multiply by negative one to flip the sign to standard ISO 8601 usage, where `+` means “ahead* of UTC and `-` means *behind* UTC.
seconds: 19800
ZoneOffset offset = ZoneOffset.ofTotalSeconds( ( int ) seconds );
offset.toString(): +05:30
Last step: get the first moment of the day in this offset. Caveat: We do not know for certain if this offset is valid on this date, as we lack a time zone.
Convert from the returned ZonedDateTime
to an OffsetDateTime
. As discussed above, determining first moment of day should always be done with a time zone, and thereby get a ZonedDateTime
. We are violating that sensible practice to use an offset, but using the returned ZonedDateTime
object would be misleading as ours would lack a true time zone, and have only a mere offset. So the OffsetDateTime
class makes our intentions clear and our code more self-documenting.
OffsetDateTime odt = ld.atStartOfDay( offset ).toOffsetDateTime();
Again, this approach using offset is not recommending, as you should be instead gathering a time zone name from the user as input rather than an offset.
UTC
Generally best to store moments in UTC.
Extract a Instant
from your OffsetDateTime
or ZonedDateTime
to get the same moment as UTC.
Instant instant = zdt.toInstant() ;
2018-04-04T18:30:00Z
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.