Why are timezones with same offset from UTC are showing different times? - java

I bumped into this issue today. I have set my clock to UTC-6.00 (Central America) time zone. I am converting the Date "06/01/2015::12:00:00 AM" ("MM/dd/yyyy::hh:mm:ss a" format) to a java Date object. And then I am reconverting the date object to String. There is a slight twist in how I am doing this though. I am listing the re conversion steps below -
Calculate UTC offset from current time zone. (-21600000)
Get all available timezone ids for this offset. (All have same offset)
Select the first time zone id. (Will have same offset)
Set this as the timezone.
Convert the date to string format using Java's Simple Date Format.
I see that the time now rendered is "06/01/2015::01:00:00 AM"
My questions :
Since the timezone offset is same during the creation and during conversion I expect the same time to be shown. But what I see is different. Why is it so?
Imagine the re conversion to be happening in the server and the creation to be happening in the client. I need to render back the same date and time to the client. How do I do this?
Please help! Any help is much appreciated.
EDIT : Following is the code. Note that I have set my current timezone to Central America.
public class TimeTest {
public static void main (String args[]) {
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy::hh:mm:ss a");
String dateInString = "01/06/2015::12:00:00 AM";
try {
Date date = formatter.parse(dateInString);
System.out.println("Before conversion --> " + formatter.format(date));
System.out.println("After conversion --> " + convertDateValueIntoString(date));
} catch (ParseException e) {
e.printStackTrace();
}
}
private static String convertDateValueIntoString(Date dateValue){
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy::hh:mm:ss a");
String date;
int offset = TimeZone.getDefault().getRawOffset();
if (offset == 0) {
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
date = dateFormat.format(dateValue);
} else {
String TZ[] = TimeZone.getAvailableIDs(offset);
String timeZone = TZ[0];
if (timeZone == null) {
date = dateFormat.format(dateValue);
} else {
TimeZone tz = TimeZone.getTimeZone(timeZone);
dateFormat.setTimeZone(tz);
date = dateFormat.format(dateValue);
}
}
return date;
}
}

Why are the times different:
The difference appears to be in the handling of daylight savings time. Playing around with setting my machine to different time zones and printing the TimeZone toString() I ended up with:
Initial: sun.util.calendar.ZoneInfo[id="America/Tegucigalpa",offset=-21600000,dstSavings=0,useDaylight=false,transitions=9,lastRule=null]
Result: sun.util.calendar.ZoneInfo[id="America/Bahia_Banderas",offset=-21600000,dstSavings=3600000,useDaylight=true,...
Note that these two TimeZones have the same offset, but one uses daylight savings time and the other does not. The offset is all your code is looking at to find an appropriate TimeZone but the date formatting also uses the daylight savings offset.
How do I handle this:
The way every project I've been on that used times did it was to have all internal representation of time be in UTC (or a similar concept). I would have your client convert the time to UTC on input (before sending it to the server), have all server storage use UTC, then when times go back to the client have the client format to the default TimeZone only for output to the user.
That way all your internal times are consistent and all your displayed times are localized for the individual instance of the client, so a user in America/Tegucigalpa may get the time as 12:00 but the user in America/Bahia_Banderas would see 1:00. Both are correct for the users those times would be displayed to.

The Answer by 1337joe is correct. I'll add a few thoughts.
This Question has much confusion floating around.
Time Zone = Offset + Rules/Anomalies/Adjustments
First, a time zone is more than an offset from UTC. A time zone is an offset plus a set of past, present, and future rules about Daylight Saving Time and other anomalies & adjustments.
So whenever possible, use a named time zone rather than a mere offset. And certainly do not mix usage of offset-only with usage of time zones and expect sensible results. That seems to be the core problem in this Question.
So, dig deeper to discover the original intent of the programmers who devised your existing stored data. I suspect they did indeed have a particular time zone in mind rather than a mere offset.
Use Proper Time Zone Names
There is no such time zone as "Central America".
As 1337Joe points out, offsets and time zones vary around Central America. For example, America/Managua is six hours behind UTC while America/Panama is five.
By the way, avoid the 3-4 letter codes for time zones such as "EST" as they are neither standardized nor unique. The one exception is UTC of course.
Specify Your Expected/Desired Time Zone
When [a] you know your incoming data represents a particular time zone or offset, albeit implicitly, and [b] you desire a certain time zone to be applied, do not call on the default time zone. That is asking for trouble. The default time zone can vary by host OS setting on machine by machine. And both the host OS settings can be changed at any time by an admin person. Thirdly, the JVM’s current default time zone can be changed at any moment during runtime by a call to TimeZone.setDefault() by any code in any thread in any app in that same JVM.
So, instead of relying on the default time zone, specify the desired time zone.
Use UTC For Logic & Storage
As 1337joe said, your business logic, data storage, data communication, and database should all be in UTC (almost always). Only apply adjustments to local time zones when expected by the user/consumer.
In comments, the author said their project is already saddled with existing stored data implicitly representing a certain time zone or offset.
java.util.Date toString
The toString method on java.util.Date automatically applies the JVM’s current default time zone. This makes working with time zone adjustments tricky. One of many reasons to avoid using the java.util.Date/.Calendar & java.text.SimpleDateFormat classes.
Use Better Date-Time Library
Use either the new java.time package in Java 8 and later (Tutorial), or the Joda-Time library (which inspired java.time).
Joda-Time
Here is some example code in Joda-Time.
According to the author’s comments, the incoming string implicitly represents a date-time value for a certain known time zone. That time zone is not stated, so I'll arbitrarily use Panama time zone. In this first part, we parse a string while specifying the time zone to be used during parsing and assigned to the resulting object.
DateTimeZone zonePanama = DateTimeZone.forID( "America/Panama" );
DateTimeFormatter formatter = DateTimeFormat.forPattern( "dd/MM/yyyy::hh:mm:ss a" );
String input = "06/01/2015::12:00:00 AM";
DateTime dateTimePanama = formatter.withZone( zonePanama ).parseDateTime( input );
System.out.println( "Input as string: " + input + " becomes object: " + dateTimePanama + " with time zone: " + dateTimePanama.getZone() );
Now let's adjust to UTC. Here this is for demonstration. In real code you would generally do any further work using this UTC value.
DateTime dateTimeUtc = dateTimePanama.withZone( DateTimeZone.UTC );
System.out.println( "dateTimeUtc: " + dateTimeUtc );
For output, our user/consumer expects a String representation in the same Panama time zone and in the same format as our input.
String output = formatter.print( dateTimeUtc.withZone( zonePanama ) );
System.out.println( "Output in special format: " + output );
When run.
Input as string: 06/01/2015::12:00:00 AM becomes object: 2015-01-06T00:00:00.000-05:00 with time zone: America/Panama
dateTimeUtc: 2015-01-06T05:00:00.000Z
Output in special format: 06/01/2015::12:00:00 AM

For question #1: The timezone offset may be the same for different timezones, but the DST may be used or not and this results in a difference.
For question #2:
For the future, you can only be safe about the time when you use UTC. (you can work around, if your time data is "recent" - see below)
For the past, you cannot reliably extract the correct time.
General conversion advice:
I worked on a project dealing with timezones and DST in a JDBC driver. There were problems storing time values and reading them back correctly. I worked /real hard/ trying to get a conversion right, so we could spare the larger works of switching to UTC. There is no correct conversion without UTC. ( /real hard/ : Think of Pulp Fiction where Jules says "I'm trying real hard to be the shepherd." :-) )
Question #2 / Future:
If your client cannot send UTC times (maybe because it is a third party system):
When your server receives time data (non UTC) from the client, which you know to be current within a few minutes (maybe somewhat longer), you could try to use your UTC time and match that to the client's time. Imagine your client sends "2015-06-01 15:45" and you know, it is now "2015-06-01 18:51 UTC", then you may interpret the client's time as "2015-06-01 18:45 UTC". If the time data sent by the client may be older than about an hour, this will fail in some cases.
Or in other words: Say your client records temperature values. If the data sent by the client is not older than a few minutes, you can match that to the UTC time. If your client records temperature of one day and sends you that at the end of the day, you cannot correctly match the time.
Why will you not be able to make a fully(!) correct conversion?
Assume the night when DST changes, so that the clock is changed from 03:00 back to 02:00. You have once 02:30 before the switch and another 02:30 after the switch. The first 02:30 has another UTC time than the second 02:30. So with UTC you are fine. But only with the "client local" 02:30, you will never be sure.
Back to the client data age: If your client sends data not older than a few minutes for 02:30 and then later another for the second 02:30, you can distinguish this on the server. If at 04:00 you get two records for 02:30, you cannot restore UTC any more.
Question #2 / Past:
Can you add a flag in the database so that new times which are transferred as UTC are marked "reliable" and the old values are not?
The output and the source:
The output from running the modified source on my system which has a TZ of "Europe/Berlin". Note that this has DST in use, but the first fetched TZ ("Algiers") has DST not in use.
formatter's TZ is sun.util.calendar.ZoneInfo[id="Europe/Berlin",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=143,lastRule=java.util.SimpleTimeZone[id=Europe/Berlin,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]]
internal date value = 1433109600000 as UTC = 31/05/2015::10:00:00 PM
Before conversion --> 01/06/2015::12:00:00 AM
Conversion: offset != 0, using TZ sun.util.calendar.ZoneInfo[id="Africa/Algiers",offset=3600000,dstSavings=0,useDaylight=false,transitions=35,lastRule=null]
After conversion --> 31/05/2015::11:00:00 PM
Setting UTC...
formatter's TZ is sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
internal date value = 1433116800000 as UTC = 01/06/2015::12:00:00 AM
Before conversion --> 01/06/2015::12:00:00 AM
Conversion: offset != 0, using TZ sun.util.calendar.ZoneInfo[id="Africa/Algiers",offset=3600000,dstSavings=0,useDaylight=false,transitions=35,lastRule=null]
After conversion --> 01/06/2015::01:00:00 AM
The source code:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class TimeTest {
static TimeZone utc = TimeZone.getTimeZone("UTC");
public static void main (String args[]) {
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy::hh:mm:ss a");
String dateInString = "01/06/2015::12:00:00 AM";
SimpleDateFormat utcformatter = new SimpleDateFormat("dd/MM/yyyy::hh:mm:ss a");
utcformatter.setTimeZone(utc);
try {
Date date = formatter.parse(dateInString);
System.out.println("formatter's TZ is " + formatter.getTimeZone());
System.out.println("internal date value = " + date.getTime() + " as UTC = " + utcformatter.format(date));
System.out.println("Before conversion --> " + formatter.format(date));
System.out.println("After conversion --> " + convertDateValueIntoString(date));
System.out.println("\nSetting UTC...\n");
formatter.setTimeZone(utc);
date = formatter.parse(dateInString);
System.out.println("formatter's TZ is " + formatter.getTimeZone());
System.out.println("internal date value = " + date.getTime() + " as UTC = " + utcformatter.format(date));
System.out.println("Before conversion --> " + formatter.format(date));
System.out.println("After conversion --> " + convertDateValueIntoString(date));
} catch (ParseException e) {
e.printStackTrace();
}
}
private static String convertDateValueIntoString(Date dateValue){
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy::hh:mm:ss a");
String date;
int offset = TimeZone.getDefault().getRawOffset();
if (offset == 0) {
System.out.println("Conversion: offset == 0 -- setting UTC");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
date = dateFormat.format(dateValue);
} else {
String TZ[] = TimeZone.getAvailableIDs(offset);
String timeZone = TZ[0];
if (timeZone == null) {
System.out.println("Conversion: offset != 0, did not find TZ, tz of dateFormat is " + dateFormat.getTimeZone());
date = dateFormat.format(dateValue);
} else {
TimeZone tz = TimeZone.getTimeZone(timeZone);
System.out.println("Conversion: offset != 0, using TZ " + tz);
dateFormat.setTimeZone(tz);
date = dateFormat.format(dateValue);
}
}
return date;
}
}

Related

How to get offset from TimeZone

I just wanted to get offset(+02:00) from TimeZone but seems like it is not working for IST, JST, EST, and BET.
TimeZone exchangeTimeZone = banker.getTimeZone();
String timeZone = ZonedDateTime.now(ZoneId.of(exchangeTimeZone.getID())).getOffset().getId();
It is returning error "Unknown time-zone ID: EST". Date object is not avilable with me.
Use ZoneId.SHORT_IDS
ZonedDateTime.now(ZoneId.of(exchangeTimeZone.getID(), ZoneId.SHORT_IDS))
.getOffset().getId();
TimeZone.toZoneId()
// Never do this in your code: Get a TimeZone with ID EST for demonstration only.
TimeZone tz = TimeZone.getTimeZone("EST");
String currentOffsetString = ZonedDateTime.now(tz.toZoneId())
.getOffset()
.getId();
System.out.println(currentOffsetString);
Output when running just now:
-05:00
Contrary to the one-arg ZoneId.of method that you used in your code, TimeZone.toZoneId() does handle the deprecated three letter abbreviations (which may be considered an advantage or a disadvantage depending on your situation and your taste). So the above code works with many such three letter abbreviations too, including EST.
I am only hesitatingly including the first code line above. There are several things wrong with it: We should not create old-fashioned TimeZone objects in our code but rely on the modern ZonedId and related classes from java.time, the modern Java date and time API. We should not rely on three letter time zone abbreviations either. They are deprecated, not standardized and typically ambiguous. EST, for example, may mean Australian Eastern Standard Time or North American Eastern Standard Time. To increase confusion some will expect you to get Eastern Time with summer time (DST) in summer. With TimeZone you don’t. You get a time zone that uses standard time all year. The same is not true for AST, PST nor CST.
However you often cannot control what you get from an API. And if you’re unlucky enough to get an old-fashioned TimeZone object with ID EST, the above code shows you the conversion you need to get into the realm of java.time.
You could try to find a mapping for an abbreviation you got:
public static ZoneId getFromAbbreviation(String abbreviation) {
return ZoneId.of(ZoneId.SHORT_IDS.get(abbreviation));
}
You could get the offsets like in this main:
public static void main(String[] args) {
ZoneId istEquivalent = getFromAbbreviation("IST");
ZoneId estEquivalent = getFromAbbreviation("EST");
ZoneId jstEquivalent = getFromAbbreviation("JST");
ZoneId betEquivalent = getFromAbbreviation("BET");
ZonedDateTime istNow = ZonedDateTime.now(istEquivalent);
ZonedDateTime estNow = ZonedDateTime.now(estEquivalent);
ZonedDateTime jstNow = ZonedDateTime.now(jstEquivalent);
ZonedDateTime betNow = ZonedDateTime.now(betEquivalent);
System.out.println("IST --> " + istEquivalent + " with offset " + istNow.getOffset());
System.out.println("EST --> " + estEquivalent + " with offset " + estNow.getOffset());
System.out.println("JST --> " + jstEquivalent + " with offset " + jstNow.getOffset());
System.out.println("BET --> " + betEquivalent + " with offset " + betNow.getOffset());
}
the output is
IST --> Asia/Kolkata with offset +05:30
EST --> -05:00 with offset -05:00
JST --> Asia/Tokyo with offset +09:00
BET --> America/Sao_Paulo with offset -03:00
As you can see, EST simply doesn't have a zone name, just an offset.

Parse TimeZone and remove the Country/State in Java

I need to get the System DateTime but do not need the [America/New_York] using the below code.
Any suggestions?
String timestampAtGMT = DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneId.systemDefault()).format(Instant.now());
String dateInAmerica = timestampAtGMT.trim();
System.out.println("In 'GMT-04:00' Time Zone:" + dateInAmerica);
Code Output :
In 'GMT-04:00' Time Zone:2020-03-23T21:39:49.419-04:00[America/New_York]
Expected Output : In 'GMT-04:00' Time Zone:2020-03-23T21:39:49.419-04:00
One solution is to remove .withZone(ZoneId.systemDefault()), and then change Instant.now() to OffsetDateTime.now(). With this, your new snippet looks like:
String timestamp = DateTimeFormatter.ISO_DATE_TIME.format(OffsetDateTime.now());
System.out.println("In 'GMT-04:00' Time Zone: " + timestamp);
And the output is:
In 'GMT-04:00' Time Zone: 2020-03-23T21:52:10.794463-04:00
By default, OffsetDateTime#now uses your system clock's default time-zone, so there's no need to specify it.
I think that what you want is an OffsetDateTime and no formatter. Simply:
String dateInAmerica
= OffsetDateTime.now(ZoneId.systemDefault()).toString();
System.out.println("In 'GMT-04:00' Time Zone:" + dateInAmerica);
When I ran this with my JVM’s time zone set to America/New_York just now, the output I got was:
In 'GMT-04:00' Time Zone:2020-03-24T15:53:11.948127-04:00
An OffsetDateTime is a date and time with an offset (for example -04:00), but without a time zone such as America/New_York. So you get the correct offset for your time zone at this time without getting the time zone.
Technically we could leave out ZoneId.systemDefault(), but I prefer to state it there to tell the reader and myself that I have considered which time zone I want and have made a conscious choice to rely on the JVM default.

How to convert 2019-09-18T01:44:35GMT-04:00 to 2019-09-18T01:44:35-04:00 using SimpleDateFormatter

I want to convert date and time to user requested timezone. date and time is in GMT format. i tried got the solution but the final string contains GMT String in resultant date like (2019-09-18T01:44:35GMT-04:00). i don't want GMT String in the resultant output.
public static String cnvtGMTtoUserReqTZ(String date, String format, String timeZone) {
// null check
if (date == null)
return null;
// create SimpleDateFormat object with input format
SimpleDateFormat sdf = new SimpleDateFormat(format);
// set timezone to SimpleDateFormat
sdf.setTimeZone(TimeZone.getTimeZone(timeZone));
try {
// converting date from String type to Date type
Date _date = sdf.parse(date);
// return Date in required format with timezone as String
return sdf.format(_date);
} catch (ParseException e) {
//log.info("Exception in cnvtGMTtoUserReqTime ::: " + e);
}
return null;
}
Actual Output : 2019-09-18T01:44:35GMT-04:00
Expected Output: 2019-09-18T01:44:35-04:00
Proces datetime objects, not strings
Your question is put in the wrong way, which is most likely due to a design flaw in your program. You should not handle date and time as strings in your program. Always keep date and time in proper datetime objects such as Instant, OffsetDateTime and ZonedDateTime. The mentioned classes are from java.time, the modern Java date and time API, which is the best we have for keeping and processing datetime data.
So your question may for example become: How to convert a moment in time to user requested timezone? A moment in time is represented by an Instant object. And the answer to the question is:
ZoneId userRequestedTimeZone = ZoneId.of("America/New_York");
Instant moment = Instant.parse("2019-09-18T05:44:35Z");
ZonedDateTime userDateTime = moment.atZone(userRequestedTimeZone);
System.out.println(userDateTime);
Please substitute your user’s desired time zone where I put America/New_York. Always give time zone in this format (region/city). Output from the snippet as it stands is:
2019-09-18T01:44:35-04:00[America/New_York]
Assuming that you don’t want the [America/New_York] part of the output, format the datetime to the string that you want:
String dateTimeWithNoZoneId = userDateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
System.out.println(dateTimeWithNoZoneId);
2019-09-18T01:44:35-04:00
The latter output is in ISO 8601 format. This format is good for serialization, that is, if you need to convert the datetime to a machine readable textual format, for example for persistence or exchange with other systems. While also human readable, it’s not what your user prefers to see. And as I said, it’s certainly not what you should be handling and processing inside your program.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601
Use these formats:
fromFormat = "yyyy-mm-dd'T'HH:mm:sszXXX"
toFormat = "yyyy-mm-dd'T'HH:mm:ssXXX"
For more details see examples listed here

Java XMLGregorianCalendar format

I am currently stuck with XMLGregorianCalendar formatting problem and would like to seek help from you java gurus. With a function call from other system, I got a data object displayed on web page with "SUBMIT_DATE":1516032000000 and "SUBMIT_TIME":36895000 (both with returned type XMLGregorianCalendar). How can I know the correct human readable date and time in this case?
Thank you for your time and help.
Update after clarification
// We first need to check that the fields we need are defined
if (submitDate.getTimezone() == DatatypeConstants.FIELD_UNDEFINED) {
throw new IllegalStateException("No time zone defined in submit date " + submitDate);
}
if (submitDate.getYear() == DatatypeConstants.FIELD_UNDEFINED
|| submitDate.getMonth() == DatatypeConstants.FIELD_UNDEFINED
|| submitDate.getDay() == DatatypeConstants.FIELD_UNDEFINED) {
throw new IllegalStateException("Date not defined in submit date " + submitDate);
}
if (submitTime.getHour() == DatatypeConstants.FIELD_UNDEFINED
|| submitTime.getMinute() == DatatypeConstants.FIELD_UNDEFINED
|| submitTime.getSecond() == DatatypeConstants.FIELD_UNDEFINED) {
throw new IllegalStateException("Time of day not defined in submit time " + submitTime);
}
if (submitTime.getTimezone() != DatatypeConstants.FIELD_UNDEFINED
&& submitTime.getTimezone() != submitDate.getTimezone()) {
throw new IllegalStateException("Conflicting offsets " + submitDate.getTimezone()
+ " and " + submitTime.getTimezone() + " minutes");
}
// then format into a human readable string
final ZoneId userZone = ZoneId.of("Asia/Taipei");
final Locale userLocale = Locale.forLanguageTag("zh-TW");
DateTimeFormatter localizedFormatter = DateTimeFormatter
.ofLocalizedDateTime(FormatStyle.LONG)
.withLocale(userLocale);
ZonedDateTime dateTime = submitDate.toGregorianCalendar()
.toZonedDateTime()
.with(LocalTime.of(submitTime.getHour(), submitTime.getMinute(), submitTime.getSecond()))
.withZoneSameInstant(userZone);
String humanReadableDateTime = dateTime.format(localizedFormatter);
System.out.println(humanReadableDateTime);
This prints:
2018年1月16日 上午10時14分55秒
I am assuming that submitDate and submitTime are XMLGregorianCalendar objects that you have got from the complex object that you have received from a remote system. I am further assuming that you can require the date to contain a UTC offset. Though the method is called getTimezone, what it really returns is not a time zone, but an offset in minutes from UTC (or GMT). The extensive checks in the four if statements are necessary because XMLGregorianCalendar is very flexible with which fields are defined and which not.
To display the date and time in a format suitable for a user audience, you need to know that audience’s time zone and locale. Once you know those, please fill them in in the above snippet. If you trust the JVM’s settings, you may use ZoneId.systemDefault() and/or Locale.getDefault(Locale.Category.FORMAT) You may also choose between format styles FULL, LONG, MEDIUM and SHORT.
If you don’t receive an offset, you will need to rely on the date and time already being at the user’s offset. On one hand it’s simpler, on the other hand it is more fragile since if the date and time are given at another offset than the user expects, s/he will receive incorrect information, which is worse than receiving no information at all. First check that there is indeed no offset:
if (submitDate.getTimezone() != DatatypeConstants.FIELD_UNDEFINED
|| submitTime.getTimezone() != DatatypeConstants.FIELD_UNDEFINED) {
throw new IllegalStateException("Unexpected offset");
}
Also check that required fields are defined, this is the same as before. Then create a LocalDateTime object and format it:
LocalDateTime dateTime = LocalDateTime.of(
submitDate.getYear(), submitDate.getMonth(), submitDate.getDay(),
submitTime.getHour(), submitTime.getMinute(), submitTime.getSecond());
String humanReadableDateTime = dateTime.format(localizedFormatter);
I got the same result as above.
Original answer
final ZoneId userZone = ZoneId.of("Asia/Taipei");
final Locale userLocale = Locale.forLanguageTag("zh-TW");
ZonedDateTime submitDateTime
= Instant.ofEpochMilli(submitDate + submitTime).atZone(userZone);
DateTimeFormatter localizedFormatter = DateTimeFormatter
.ofLocalizedDateTime(FormatStyle.LONG)
.withLocale(userLocale);
String humanReadableDateTime = submitDateTime.format(localizedFormatter);
System.out.println(humanReadableDateTime);
This prints
2018年1月16日 上午10時14分55秒
To display the date and time in a format suitable for a user audience, you need to know that audience’s time zone and locale. Once you know those, please fill them in in the first two lines of the above snippet. If you trust the computer’s settings, you may use ZoneId.systemDefault() and/or Locale.getDefault(Locale.Category.FORMAT) You may also choose between format styles FULL, LONG, MEDIUM and SHORT. For this purpose I think you can ignore the information that the returned type is XMLGregorianCalendar.
As #user unknown in another answer I am assuming that you can just add the two numeric values. The first almost certainly denotes milliseconds since the epoch, the sum probably too. So why were they passed as two values and not just one? My best guess is that they pass the date separately for any client that just needs the date and not the time of day. The date value falls at midnight in time zones at offset +08:00, this would agree with China, Philippines, Malaysia and a dozen other time zones.
If instead of the numbers you have got two XMLGregorianCalendar objects, getting the date and time is a different story, but you may still use the same way of formatting them.
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(date);
return DatatypeFactory.newInstance().newXMLGregorianCalendar(
calendar);
This should work..
Pass your millisecs
Your inputs look like they're just the date without time in milliseconds and the time without date in milliseconds.
If you divide both values by 1000:
date -d #1516032000
Mo 15. Jan 17:00:00 CET 2018
date -d #36895
Do 1. Jan 11:14:55 CET 1970
Well - but why 17:00:00? Maybe a time zone issue.
Here is the aggregate:
date -d #$((1516032000+36895))
Di 16. Jan 03:14:55 CET 2018
The various date/time formats for Java have methods, which take a long parameter for seconds since epoch (1.1.1970) to set the time.

Adjust String timestamp to GMT

I have a String with local time:
"2012-12-12T08:26:51+000"
I now need to create a String with GMT time based on the old String. For example, assuming 2 hours difference between local and GTM:
"2012-12-12T10:26:51+000"
I have created a SimpleDateFormat:
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss+SSSS");
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
String time = dateFormat.parse(mCreatedTime).toString();
But the time String is now in different format:
Wed Dec 12 etc
How do I get the output to be in format yyy-MM-dd'T'HH:mm:ss+SSSS but GMT time?
The dateFormat.parse() method returns an instance of Date, and when you call toString() on it the date will be printed in the default locale.
Use dateFormat.format() to get your Date value back to your required format.
As my comments on this question suggest, I believe the original poster of this question is confused and miseducated about date-time work. Nevertheless, I wrote some example code delivering exactly what Pierre asked for, along with my caveat that he is following some very bad practices.
Using Joda-Time 2.3 library and Java 7.
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;
// CAUTION: The question asked specifically for the format used here.
// But this format incorrectly uses the PLUS SIGN to mean milliseconds rather than offset from UTC/GMT.
// Very bad thing to do. Will create no end of confusion.
// Another bad thing: This code creates strings representing date-times in different time zones without indicating they are in different time zones.
// Time Zone list: http://joda-time.sourceforge.net/timezones.html
// "Atlantic/South_Georgia" is a time zone two hours behind UTC.
DateTimeZone southGeorgiaZone = DateTimeZone.forID( "Atlantic/South_Georgia" );
DateTimeFormatter formatter = DateTimeFormat.forPattern( "yyyy-MM-dd'T'HH:mm:ss+SSS" );
DateTime dateTimeInSouthGeorgia = formatter.withZone( southGeorgiaZone ).parseDateTime( "2012-12-12T08:26:51+000" );
DateTime dateTimeInUtc = dateTimeInSouthGeorgia.toDateTime( DateTimeZone.UTC );
String screwyBadPracticeDateTimeString = formatter.print( dateTimeInUtc );
System.out.println( "2012-12-12T08:26:51+000 in southGeorgiaDateTime: " + dateTimeInSouthGeorgia );
System.out.println( "same, in UTC: " + dateTimeInUtc );
System.out.println( "screwyBadPracticeDateTimeString: " + screwyBadPracticeDateTimeString );
When run…
2012-12-12T08:26:51+000 in southGeorgiaDateTime: 2012-12-12T08:26:51.000-02:00
same, in UTC: 2012-12-12T10:26:51.000Z
screwyBadPracticeDateTimeString: 2012-12-12T10:26:51+000

Categories