Imagine I have some datetime value coming from one system, and a timezone information (source and target time zones) coming from another. I need to convert the datetime from source to target time zone.
For example, let's say I get a datetime in the Moscow time zone. I need to convert it to the Berlin time zone. How can I do it using Joda Time?
private static final String TIMEZONE_BERLIN_ID = "Europe/Berlin"; //$NON-NLS-1$
private static final DateTimeZone TIMEZONE_BERLIN = DateTimeZone
.forID(TIMEZONE_BERLIN_ID);
private static final DateTimeZone TIMEZONE_MOSCOW = DateTimeZone
.forID("Europe/Moscow"); //$NON-NLS-1$
@Test
public void testDateTimeConversion() {
final Date sourceDateTime = new DateTime(2015, 3, 15, 12, 55).toDate();
// We assume that sourceDateTime is in TIMEZONE_MOSCOW. We want to convert it to TIMEZONE_BERLIN.
// Note that the conversion should work regardless whether sourceDateTime contains any timezone
// information. It must be converted from TIMEZONE_MOSCOW to TIMEZONE_BERLIN (regardless of whether
// a timezone is specified in it).
final Date expectedResult =
new DateTime(2015, 3, 15, 12 - 2, 55).toDate(); // At 12:55 in Moscow, it is 10:55 in Berlin.
final Date actualResult =
new DateTime(sourceDateTime, TIMEZONE_MOSCOW).toDateTime(
TIMEZONE_BERLIN).toDate();
Assert.assertEquals(expectedResult, actualResult);
}
Why does actualResult
contain wrong datetime?
new DateTime(sourceDateTime, TIMEZONE_MOSCOW).withZone(TIMEZONE_BERLIN).toDate()
doesn't work, either.
A java.util.Date
object does not contain timezone information. It's just a wrapper around a number of milliseconds since 01-01-1970, 00:00:00 GMT. You cannot have a Date
object that is in a specific timezone. A Date
object always refers to an "absolute" point in time. You should not pretend that the Date
object contains a date and time in a particular timezone (such as Moscow or Berlin timezone).
Instead, you specify the timezone when you format the Date
object for display, by setting the timezone you want to see the Date
in on the DateFormat
object:
DateFormat df1 = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss z");
df1.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
DateFormat df2 = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss z");
df2.setTimeZone(TimeZone.getTimeZone("Europe/Moscow"));
Date now = new Date();
// Note: The same Date object, but displayed in different timezones
System.out.println("The time in Berlin: " + df1.format(now));
System.out.println("The time in Moscow: " + df2.format(now));
This one seems to work:
@Test
public void testDateTimeConversion() {
final Date sourceDateTime = new DateTime(2015, 3, 15, 12, 55, TIMEZONE_MOSCOW).toDate();
final Date expectedResult =
new DateTime(2015, 3, 15, 12 - 2, 55, TIMEZONE_BERLIN).toLocalDateTime().toDate();
final DateTime timeInMoscow =
new DateTime(sourceDateTime, TIMEZONE_MOSCOW);
final DateTime timeInBerlin = timeInMoscow.toDateTime(TIMEZONE_BERLIN);
final Date actualResult = timeInBerlin.toLocalDateTime().toDate();
Assert.assertEquals(expectedResult, actualResult);
}
I think this one addresses your concern. Just convert this logic to JUnit then it will work.
DateTimeZone TIMEZONE_BERLIN = DateTimeZone.forID("Europe/Berlin");
DateTimeZone TIMEZONE_MOSCOW = DateTimeZone.forID("Europe/Moscow");
//moscow timezone 12:55
DateTime sourceTimeMoscow = new DateTime(2015, 3, 15, 12, 55, TIMEZONE_MOSCOW);
//berlin time expected 10:55
Date expectedResult = new DateTime(2015, 3, 15, 10, 55, TIMEZONE_BERLIN).toLocalDateTime().toDate();
//get actual result in Berlin in reference to Moscow
Date actualResult = new DateTime(sourceTimeMoscow, TIMEZONE_BERLIN).toLocalDateTime().toDate();
//for display purposes
System.out.println(expectedResult); //expected result Berlin Time
System.out.println(actualResult); //actual result Berlin Time
I hope this solution addresses your issue.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.