Converting Between Date/Time and Text To convert a string to a Date/Time value, use DATETIMEVALUE() passing in a string in the format “YYYY-MM-DD HH:MM:SS”. This method returns the Date/Time value in GMT.
You can make use of the following DateFormat. SimpleDateFormat myDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); myDate. setTimeZone(TimeZone. getTimeZone("UTC")); Date newDate = myDate.
The java. util. Date has no concept of time zone, and only represents the number of seconds passed since the Unix epoch time – 1970-01-01T00:00:00Z. But, if you print the Date object directly, the Date object will be always printed with the default system time zone.
If you cannot change the OS or the JVM timezone, you can still convert a Java Date/Time or Timestamp to a specific time zone using the following two JDBC methods: PreparedStatement#setTimestamp(int parameterIndex, Timestamp x, Calendar cal) – to convert the timestamp that goes to the database.
For me, the simplest way to do that is:
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
//Here you say to java the initial timezone. This is the secret
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
//Will print in UTC
System.out.println(sdf.format(calendar.getTime()));
//Here you set to your timezone
sdf.setTimeZone(TimeZone.getDefault());
//Will print on your default Timezone
System.out.println(sdf.format(calendar.getTime()));
Understanding how computer time works is very important. With that said I agree that if an API is created to help you process computer time like real time then it should work in such a way that allows you to treat it like real time. For the most part this is the case but there are some major oversights which do need attention.
Anyway I digress!! If you have your UTC offset (better to work in UTC than GMT offsets) you can calculate the time in milliseconds and add that to your timestamp. Note that an SQL Timestamp may vary from a Java timestamp as the way the elapse from the epoch is calculated is not always the same - dependant on database technologies and also operating systems.
I would advise you to use System.currentTimeMillis() as your time stamps as these can be processed more consistently in java without worrying about converting SQL Timestamps to java Date objects etc.
To calculate your offset you can try something like this:
Long gmtTime =1317951113613L; // 2.32pm NZDT
Long timezoneAlteredTime = 0L;
if (offset != 0L) {
int multiplier = (offset*60)*(60*1000);
timezoneAlteredTime = gmtTime + multiplier;
} else {
timezoneAlteredTime = gmtTime;
}
Calendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(timezoneAlteredTime);
DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");
formatter.setCalendar(calendar);
formatter.setTimeZone(TimeZone.getTimeZone(timeZone));
String newZealandTime = formatter.format(calendar.getTime());
I hope this is helpful!
As always, I recommend reading this article about date and time in Java so that you understand it.
The basic idea is that 'under the hood' everything is done in UTC milliseconds since the epoch. This means it is easiest if you operate without using time zones at all, with the exception of String formatting for the user.
Therefore I would skip most of the steps you have suggested.
Alternatively, you can use Joda time. I have heard it is a much more intuitive datetime API.
Instant.ofEpochMilli( 1_317_816_735_000L )
.atZone( ZoneId.of( "Pacific/Auckland" ) )
.format( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( new Locale( "en" , "NZ" ) ) )
…also…
LocalDateTime.parse( "2011-10-06 03:35:05".replace( " " , "T" ) )
.atZone( ZoneId.of( "Pacific/Auckland" ) )
The Question and most Answers use outdated legacy date-time classes from the earliest versions of Java. These old classes have proven to be troublesome and confusing. Avoid them. Instead use the java.time classes.
Your input string is nearly in standard ISO 8601 format. Just replace the SPACE in the middle with a T
.
String input = "2011-10-06 03:35:05".replace( " " , "T" );
LocalDateTime
Now parse as a LocalDateTime
because the input lacks any information about offset-from-UTC or time zone. A LocalDateTime
has no concept of offset nor time zone, so it does not represent an actual moment on the timeline.
LocalDateTime ldt = LocalDateTime.parse( input );
ZoneOffset
You seem to be saying that from the business context you know the intention of this string is to represent a moment that is 13 hours ahead of UTC. So we instantiate a ZoneOffset
.
ZoneOffset offset = ZoneOffset.ofHours( 13 ); // 13 hours ahead of UTC, in the far east of the globe.
OffsetDateTime
Apply it to get an OffsetDateTime
object. This becomes an actual moment on the timeline.
OffsetDateTime odt = ldt.atOffset( offset);
ZoneId
But then you mention New Zealand. So you had a specific time zone in mind. A time zone is an offset-from-UTC plus a set of rules for handling anomalies such as Daylight Saving Time (DST). So we can specify a ZoneId
to a ZonedDateTime
rather than a mere offset.
Specify a proper time zone name. 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(!). For example, Pacific/Auckland
.
ZoneId z = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime
Apply the ZoneId
.
ZonedDateTime zdt = ldt.atZone( z );
You can easily adjust into another zone for the very same moment on the timeline.
ZoneId zParis = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtParis = zdt.withZoneSameInstant( zParis ); // Same moment in time, but seen through lens of Paris wall-clock time.
I strongly recommend against handling date-time values as a count from epoch, such as milliseconds from the start of 1970 UTC. But if you must, create a Instant
from such a number.
Instant instant = Instant.ofEpochMilli( 1_317_816_735_000L );
Then assign a time zone as seen above, if desired, to move away from UTC.
ZoneId z = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime zdt = instant.atZone( z );
Your value of 1_317_816_735_000L
is:
2011-10-05T12:12:15Z
(Wed, 05 Oct 2011 12:12:15 GMT)2011-10-06T01:12:15+13:00[Pacific/Auckland]
(Thursday October 06, 2011 01:12:15 in Auckland New Zealand).To generate a string in standard ISO 8601 format, simply call toString
. Note that ZonedDateTime
wisely extends the standard format by appending the name of the time zone in square brackets.
String output = zdt.toString();
For other formats, search Stack Overflow for DateTimeFormatter
class. Already covered many times.
Specify a FormatStyle
and a Locale
.
Locale l = new Locale( "en" , "NZ" );
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( l );
String output = zdt.format( f );
Note that time zone has nothing to do with locale. You can have a Europe/Paris
date-time displayed in Japanese language & cultural norms, or a Asia/Kolkata
date-time displayed in Portuguese language and Brazil cultural norms.
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date
, .Calendar
, & java.text.SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).
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.
The solution is actually quite simple (pure, simple Java):
System.out.println(" NZ Local Time: 2011-10-06 03:35:05");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localNZ = LocalDateTime.parse("2011-10-06 03:35:05",formatter);
ZonedDateTime zonedNZ = ZonedDateTime.of(localNZ,ZoneId.of("+13:00"));
LocalDateTime localUTC = zonedNZ.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime();
System.out.println("UTC Local Time: "+localUTC.format(formatter));
OUTPUT IS:
NZ Local Time: 2011-10-06 03:35:05
UTC Local Time: 2011-10-05 14:35:05
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With