Creating a datetime object in a particular timezone in JodaTime - java

I have a date, timezone and time as Strings, and I want to construct a JodaTime object with that date and time for that timezone. The code I have written is
String dateString = "2016-06-02";
String time = "01:00:00";
String timezone = "Australia/Brisbane";
DateTime dateInTimezone = DateTime.parse(dateString+" "+time,DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"))
.withZone(DateTimeZone.forID(timezone));
I would expect dateInTimezone to be created with value 2016-06-02T01:00:00.000+10:00 but it gets created with value 2016-06-02T18:00:00.000+10:00. My systems timezone is in America\Los_Angeles. From what I understand it takes the time I pass as a parameter in my systems timezone and converts that to the timezone I specify. Probably thats why 01:00:00 got internally converted to 18:00:00.
How do I create a joda time object with specified time and specified timezone, without any conversions?

Add the timezone to your formatter before parsing:
String dateString = "2016-06-02";
String time = "01:00:00";
String timezone = "Australia/Brisbane";
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
.withZone(DateTimeZone.forID(timezone));
DateTime dateInTimezone = DateTime.parse(dateString+" "+time, formatter);
Another option is to do it your way, but call DateTime.withZoneRetainFields(), but then there's the risk of the parse failing if it falls out on an invalid date (e.g. between a DST gap) in the initial timezone.

Related

Java exact Date to String conversion (no local GMT offset)

I'm trying to do a very simple task.
Convert a time (long myTime) in epoch seconds, to a String (but without any adjustment).
DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
Instant AA = Instant.ofEpochSecond(myTime);
String reportDate = df.format(Date.from(AA));
The "reportDate" is automatically adjusted with GMT offset of Windows.
I need instead the exact instant to string conversion.
I'm new on Java ....
Set the time zone specifically
df.setTimeZone(TimeZone.getTimeZone("GMT"));
This sets the offset to whatever you need so it will output the same date time on any server.

Java: Compare dates on same timezone

Given:
SimpleDateFormat sd = new SimpleDateFormat ("yy-MM-dd hh:mm:ss.SSS");
sd.setTimeZone(TimeZone.getTimeZone("GMT"));
Date d = sd.parse("a date similar to now on local computer");
if I compare d.getTime() with new Date().getTime(), the values are different with more than one hour. Why?
Check your timezones. You are comparing a time that isn't in GMT.
You're explicitly setting your SimpleDateFormat to parse in GMT, which means that when you parse the current clock time, you're getting the moment of time when that time occurred, in the GMT time zone. If you're not in the GMT time zone, that won't be "now".
Date objects don't know anything about timezones - there is no explicit timezone information in a Date object. A Date object represents an "absolute" moment in time (it's a timestamp). This means you should not think of a Date object as "a date in a certain timezone" - it has no timezone.
Suppose that from some source you get a String that contains a date and time, without an explicit timezone mentioned in it, for example: 2014-12-16 17:30:48.382. Suppose that you know that this date and time is in the GMT timezone.
You could then parse it to a Date object with an appropriate SimpleDateFormat object:
DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
// Set the timezone of the SimpleDateFormat to GMT, because you know the string
// should be interpreted as GMT
fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
// Parse the String into a Date object
Date dateTime = fmt.parse("2014-12-16 17:30:48.382");
// Date object which is set to "now"
Date now = new Date();
// Compare it to "now"
if (dateTime.before(now)) {
System.out.println("The specified date is in the past");
} else if (dateTime.after(now)) {
System.out.println("The specified date is in the future");
} else {
System.out.println("The specified date is now");
}
If you want to print the date in a certain timezone, then do so by formatting it with a SimpleDateFormat set to the appropriate timezone.
DateFormat outfmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
outfmt.setTimeZone(TimeZone.getTimeZone("EDT"));
// Will print dateTime in the EDT timezone
System.out.println(outfmt.format(dateTime));

ISO8601 to DateTime with time zone information preserved

Below is a deserialization of an ISO8601 date string that contains time zone information. Notice that the time zone information is lost:
scala> val date1 = new DateTime().withZone(DateTimeZone.forID("Europe/Berlin"))
date1: org.joda.time.DateTime = 2013-09-22T18:42:15.348+02:00
scala> date1.getZone()
res45: org.joda.time.DateTimeZone = Europe/Berlin
scala> val date2 = new DateTime(date1.toString())
date2: org.joda.time.DateTime = 2013-09-22T19:42:15.348+03:00
scala> date2.getZone()
res46: org.joda.time.DateTimeZone = Europe/Vilnius
scala> date1.getZone() == date2.getZone()
res47: Boolean = false
Time zone information (UTC offset) is serialized, as in +03:00 and +02:00 at the end of the ISO8601 strings, but it is lost after deserialization. As you can see the date2 DateTime object, which I expected to be a copy of date1 has the system's UTC offset instead of +02:00, which date1 had.
How do I deserialize an ISO8601 string as to preserve the UTC offset?
The constructor you are using, new DateTime(Object instant), (actually passed through to BaseDateTime) doesn't parse, instead it converts the given object (in your case, a String).
Long story short, it uses the default time zone:
The constructor considers the passed parameter an Instant and requests an InstantConverter from ConverterManager
The constructor calls getInstantMillis() on that StringConverter
That method actually does use a standard ISO 8601 DateTimeFormatter, however instead of parse it calls parseMillis().
parseMillis, as you can see from the javadocs, returns a date in the default time zone.
Use DateTime.parse instead:
DateTime date2 = DateTime.parse(date1.toString());
// 2013-09-22T19:21:48.461+02:00

How to convert Joda-Time DateTime to java.util.Date and vice versa?

Is it possible to do that? If yes, then how do I do the conversion from Joda-Time to Date and vice versa?
To convert Java Date to Joda DateTime:-
Date date = new Date();
DateTime dateTime = new DateTime(date);
And vice versa:-
Date dateNew = dateTime.toDate();
With TimeZone, if required:-
DateTime dateTimeNew = new DateTime(date.getTime(), timeZone);
Date dateTimeZone = dateTime.toDateTimeAtStartOfDay(timeZone).toDate();
You haven't specified which type within Joda Time you're interested in, but:
Instant instant = ...;
Date date = instant.toDate();
instant = new Instant(date);
// Or...
instant = new Instant(date.getTime());
Neither Date nor Instant are related to time zones, so there's no need to specify one here.
It doesn't make sense to convert from LocalDateTime / LocalDate / LocalTime to Date (or vice versa) as that would depend on the time zone being applied.
With DateTime you can convert to a Date without specifying the time zone, but to convert from Date to DateTime you should specify the time zone, or it will use the system default time zone. (If you really want that, I'd specify it explicitly to make it clear that it's a deliberate choice.)
For example:
DateTimeZone zone = DateTimeZone.forID("Europe/London");
Date date = ...;
DateTime dateTime = new DateTime(date.getTime(), zone);
To Convert from Java Date to Joda Time of Date:
To convert from Date to DateTime time zone needed to be specified.
To convert from java.util Date to Joda Time of Date you just need to pass the java.util Date and time zone to the constructor of Joda Time of Date.
java.util.Date date = new java.util.Date(System.currentTimeMillis());
DateTimeZone dtz = DateTimeZone.getDefault();// Gets the default time zone.
DateTime dateTime = new DateTime(date.getTime(), dtz);
To Convert from Joda Time of Date to Java Date:
For the reverse case Joda DateTime has a method toDate() which will return the java.util Date.
DateTime jodaDate = new DateTime();
java.util.Date date = jodaDate.toDate();
For More Details Visit Here

How do I convert a String in a different timezone to UTC using Joda-Time

I managed to convert a valid date string in a different timezone to UTC as follows.
String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
DateTimeFormatter DATETIME_FORMATTER = DateTimeFormat.forPattern(DATE_FORMAT);
DateTimeZone dateTimeZone = DateTimeZone.forID("-03:00");
//date is 2000-01-01 00:00:00 -03:00
DateTime date = DATETIME_FORMATTER.withZone(dateTimeZone).parseDateTime("2000-01-01 00:00:00"));
System.out.println("Current date is: " + date.toString());
//now convert to UTC
DateTime convertedDate = date.toDateTime(DateTimeZone.UTC);
System.out.println("Converted date: " + date.toString());
The result is
Current date is: 2000-01-01T00:00:00.000-03:00
Converted date: 2000-01-01T03:00:00.000Z
Is there a shorter/better way of doing this? I want the final date to be a Joda-Time DateTime object.
You can convert the time zone of any DateTime using withZone(). If the input string doesn't specify the time-zone offset then you have to add it as you are doing, so your code is fairly optimal.
One improvement over your example code might be replacing the hard-coded "-3:00" offset with a time zone name. That would allow Joda-Time to make adjustments for any possible Daylight Saving Time (DST). See doc for DateTimeZone.forID().
This:
DateTimeZone dateTimeZone = DateTimeZone.forID("America/Sao_Paulo");
instead of this:
DateTimeZone dateTimeZone = DateTimeZone.forID("-03:00");
Time Zone list (possibly outdated, read note):
http://joda-time.sourceforge.net/timezones.html

Categories