I'm trying to call a .Net webservice from Java. I have a java.sql.Date that I am converting to a Calendar which then gets passed through to .Net as a DateTime.
Unfortunately, when it gets to the other side it is a day behind the date that was sent. This is a known issue as per (http://wiki.apache.org/ws/FrontPage/Axis/DotNetInterop) and I'm sure there is a way around it but I just can't seem to find it.
Does anyone know of a way to correctly convert a java.sql.Date to a Calendar so that there is no 24 hour offset issue?
The code I have at the moment is as follows:
java.sql.Date myDate = Date.valueOf("2011-04-11");
Calendar calendarDate = Calendar.getInstance();
calendarDate.clear();
calendarDate.setTime(myDate); //we then pass calendarDate off to webservice...
When I look at the timezone info I see the following:
In Java the following gets me "Eastern Standard Time (New South Wales)":
calendarDate.getTimeZone().getDisplayName();
In .Net the following gets me "AUS Eastern Standard Time":
TimeZone.CurrentTimeZone.StandardName;
As far as I am currently aware, both Java and .Net have the local time in the same timezone...
I'm not sure if this is the correct thing to do...but it seems to have fixed my problem...
java.sql.Date myDate = Date.valueOf("2011-04-11");
Calendar calendarDate = Calendar.getInstance();
//normalise the SQL date
//http://download.oracle.com/javase/6/docs/api/java/sql/Date.html
calendarDate.set(Calendar.HOUR_OF_DAY, 0);
calendarDate.set(Calendar.MINUTE, 0);
calendarDate.set(Calendar.SECOND, 0);
calendarDate.set(Calendar.MILLISECOND, 0);
calendarDate.setTime(myDate);
calendarDate.set(Calendar.DST_OFFSET, 0); //Clear the daylight savings offset
calendarDate.set(Calendar.ZONE_OFFSET, 0); //Clear the timezone offset
Setting the offset to zero seems to allow it to avoid the offset issue altogether.
I think this works because the Java and .Net webservices seem to interact like this:
Java dates are GMT plus an offset
Axis seems to pass the date to .Net without the offset information.
.Net then assumes local time for a time that is actually GMT...which leads to offset problems of +/-24 hours.
I think my fix of setting the offset to zero after setting the date causes the Calendar to keep the date consistent with local time in the absence of the offset. Thus when the date gets to the .Net webservice the assumption of local time is correct.
I have no idea if that is the case or not and would appreciate a better explanation...but for now, unless told otherwise, this solution appears to work...
according to that article, .net always handles dates in the local timezone (wow, is that broken). so, you must determine the timezone of the .net service and set that timezone on your Calendar instance.
Related
I support a large enterprise app and we have two classes that use LocalDate.now to get a timestamp, one uses joda time, one uses Java time. Typically we restart every night, but earlier this week we weren't able to. On the second day of the application running, the class using joda time returned the correct date (20200505) but the class using Java time returned the date the application was turned on (20200504).
Both classes make a new call to LocalDate.now in the method each time it's called.
Java time:
String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
//Use timestamp
Joda time:
LocalDate date = LocalDate.now();
String format1 = date.toString("MM/dd/yyyy");
//Use date
Why does the Java 8 implementation of LocalDate.now return the wrong date after the server date has changed without an application restart?
The class with the issue is an enum, and it turns out in another call the value of a field in the enum was being changed and saved, so when the app was doing the timestamp replacement, the placeholder was no longer in the enum after the first call. Who knows why. Fixing this fixed the issue, no problem with Java time.
The local date depends on the default time zone, as there is no global date.
I assume that the time zone in your server is off, and this still returns yesterday's date for a few hours after midnight. This is a quite common configuration error when configuring the server to run in UTC whilst the actual timezone is more on the eastern side.
https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html#getDefault--
If the cached default TimeZone is available, its clone is returned.
Otherwise, the method takes the following steps to determine the
default time zone.
Use the user.timezone property value as the default time zone ID if it's available.
Detect the platform time zone ID. The source of the platform time zone and ID mapping may vary with implementation.
Use GMT as the last resort if the given or detected time zone ID is unknown.
You can easily verify that by getting the LocalDate.now() after changing the default time zone:
TimeZone defaultTimeZone = TimeZone.getDefault();
try {
Arrays.stream(TimeZone.getAvailableIDs())
.map(TimeZone::getTimeZone)
.forEach(timeZone -> {
TimeZone.setDefault(timeZone);
System.out.printf("%s in %s (%s)\n",
LocalDate.now(), timeZone.getID(), timeZone.getDisplayName());
});
} finally {
TimeZone.setDefault(defaultTimeZone);
}
So the question is: which time zone does your server use?
I have a timezone-delicate report in Jasper and I can't really seem to figure out how to show a few dates relative to a timezone.
I have a view which returns dates with the following format:
"2015-03-02 11:45:00+01"
"2015-03-02 23:59:59+01"
"2015-03-03 00:00:00+01"
"2015-03-03 08:00:00+01"
"2015-03-03 09:20:00+01"
"2015-03-03 11:00:00+01"
"2015-03-03 09:00:00+01"
"2015-03-03 09:30:00+01"
etc (notice the +01 at the end)
In my report, I have:
new SimpleDateFormat("HH:mm", $P{REPORT_LOCALE}).format($F{start_date});
However, for example, for "2015-03-02 11:45:00+01" I don't get 12:45 shown, I get 11:45.
Also, I need to sum-up the hours (they're intervals) and this gives me a 1hr (in this case) error.
Can anyone help me show the correct hour?
Thanks!
SimpleDateFormat takes a Date, not a Calendar - which means it can't be provided the time zone in the value itself.
Assuming you need to stick with SimpleDateFormat (rather than using Joda Time or Java 8's java.time, for example) then you'll need to set the time zone on the SimpleDateFormat itself. If you need to take the time zone from the data (rather than having a report-wide zone) then you'll need to call setTimeZone before formatting each value - but of course, you'll also need to make sure you've got the time zone in the value, and java.sql.Timestamp doesn't have any notion of a time zone, as far as I'm aware.
I have a requirement of getting UTC time , hence in many places iam using below code for calcualting utc time.
System.currentTimeMillis() ;
Iam in IST - (GMT+5:30) , System.currentTimeMillis() - should display UTC time (IST-5:30) , instead it is taking current time (GMT+5:30).
I donot want to use the Apache of joda date and time api. i want to use the Java api itslef. Help me in resolve my issue.
System.currentTimeMillis() just returns a long - that's not in any sort of date format.
If you're actually using:
Date date = new Date(System.currentTimeMillis());
System.out.println(date);
then you're just seeing the result of Date.toString(), which always uses the system default time zone.
Use DateFormat (e.g. SimpleDateFormat) to specify the calendar system (typically Gregorian), time zone and format you want to use. For example:
Date date = ...;
DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss",
Locale.US);
format.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String result = format.format(date);
As an aside, I'd strongly recommend abstracting the idea of "getting the current time" into an interface which you implement in one case using System.currentTimeMillis() (or equivalently, just new Date()) but implement for testing purposes with a value you can set and update at will. Then inject this "clock" interface into anything which needs to access the current date/time. It makes it much easier to test time-based components.
(I'd also strongly recommend using Joda Time or the java.time package from Java 8 if you possibly can. I know you've said you don't want to, but I suspect that's because you haven't spent as much time swearing at java.util.Date and java.util.Calendar as some of us. Both of those alternatives will lead to much cleaner code which is much easier to read and reason about. If you're trying to avoid a one-time hit of getting Joda Time into your build process, weigh that against the amount of time you're likely to spend maintaining your code. Or just update to Java 8... Java 7 will be out of free-update support soon anyway...)
Quick summary of my issue first, then details further below.
I have a Calendar date with 00:00:00 as the time as it's not important to the business. This value is sent to a webservice which generates a XML in which the value ends up in the following format : 2014-09-12T07:55:07.000Z. I have noticed that this is the original value converted to a +0 timezone (UTC) (ours is CET, +1, but currently CEST, +2, because of DST).
I currently have no idea whether the system reading the XML takes timezones into account or would extract 2014-09-12 and assume it's in the +2 timezone.
What I've noticed is that sending "2014-09-12 00:00:00" local time (tz +2) ends up as 2014-09-11T22:00:00.000Z in the XML. No big surprise, it converted it... but if it's interpreted as is by the other system, it will think the date is a day earlier than it should be.
What can be done to ensure this gets interpreted as intended?
I was thinking of using noon instead of midnight to make sure timezone shifts wouldn't impact interpretation, but it feels like a dirty trick. Or maybe I should cheat and have the Calendar timezone be +0 so it's not time-shifted when put in the XML?
Q&A
Why do you "send a Calendar to a webservice"?
The application is in Coldfusion 7. To communicate with SOAP webservices, the server generates a set of Java classes that fit the definition of the argument expected by the webservice. The argument is apparently a single big object with a lot of attributes and sub-attributes. So one instantiates the main Java class and uses setters and further instanciations of other classes to "fill out" all the attributes.
Do you have to use Calendar?
Yes, the Java object definition cannot be changed. It expects Calendar for all dates.
What's this 2014-09-11T22:00:00.000Z format?
I have no idea. This seems to be what the end system expects for dates.
You should use JODA
Unless JODA classes extend Calendar and are compatible with Java 1.3 (current Java version on the Coldfusion server -- yes it's old), I doubt it will work.
How much can you do on the other system?
The other system is the responsibility of a different team and is apparently very hard to change. I expect the solution will have to be found on the side of our application.
Although the time value in your Calendar object is not important to your business, it is important to the webservice that you use and have no control over. The calendar object specifies an instant in time, so you must make sure that instant is in the day that is important to you. I recommend you use midday, as you suggested already. I also recommend that you create your Calendar object in the UTC timezone:
Calendar myCalendar=Calendar.getInstance(TimeZone.getTimeZone("UTC"));
I would like to start by saying that I've read several threads similar to this one, but none of them really solved my problem.
I would also like to state that I've tried to use SimpleDateFormat and joda.DateTime without any success.
The problem is the following:
I have a Calendar object that holds the information about a specific date: 2008-04-30T00:00:00Z
When using the calendar.getTime() method I can get different results because I know that that method is looking for the local value
Thus:
UK: 2008-04-30T01:00:00.000+0100
US: 2008-04-30T20:00:00.000-0400
But I would like to get a Date object that holds just the Date and Time values "2008-04-30T00:00:00" ignoring completely any timezone.
How can I do that?
As I mentioned before I tried to use
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
but I always end up with the same results.
Any help would be really appreciated
Cheers.
Found out that you can clear the Timezone by using code below:
Calendar cal = Calendar.getInstance();
cal.clear(Calendar.ZONE_OFFSET);
Calendars and Dates mean nothing without a TimeZone.
Calendars and dates cannot exist without a timezone.
You can't ignore completely any timezone.
You can create a Calendar for Greenwich Mean Time (offset zero) like this:
TimeZone zone = TimeZone.getTimeZone("Etc/GMT");
Calendar cal = Calendar.getInstance(zone);
This represents a Date/Calendar that is only meaningful in the GMT timezone.
It sounds like you want a timestamp, which represents an instant in time.
As others have pointed out, Calendar and Date objects cannot exist without a time zone.
I believe you may want to use the LocalDateTime class introduced in Java 8 with the new time API:
LocalDateTime literal = LocalDateTime.of(2008, 4, 30, 0, 0, 0);
LocalDateTime parsed = LocalDateTime.parse("2008-04-30T00:00:00"); // ISO-8601 by default
Assert.assertEquals(literal, parsed);
Do you use a standard constructor for initializing Calendar? What if you used the constructor which allows to specify the time zone and locale?
protected Calendar(TimeZone zone, Locale aLocale)
Old, but still incorrect.
"When using the calendar.getTime() method I can get different results because I know that that method is looking for the local value"
That is a misconception. getTime() will get the Milliseconds only. Countet as GMT.
ONLY during formatting of the Output the time zone becomes relevant. Sind the original poster did not show the code, it can not be decided, where the error occurs.