Assuming I have a timestamp "1355409000003" as a String, is there a way to specify a DateTime format that parses that into a Joda DateTime?
I.e., I can parse "12/01/2012" with format "MM/dd/YYYY" and "2012-12-01 04:27" with "YYYY-MM-dd HH:mm", but how can I parse "1355409000003"?
edit: not using a different constructor, assume I MUST specify a String format to parse with
tl;dr
Just parse your String to long. No big deal.
Use java.time classes that supplant Joda-Time project.
Instant.ofEpochMilli(
Long.parseLong( "1355409000003" )
)
2012-12-13T14:30:00.003Z
Parse String to long
Your Question does not really make sense. If you get a string representing the count of milliseconds since epoch of 1970-01-01T00:00Z, then convert that String to a long and pass to the constructor of the Joda-Time DateTime type.
This was shown in an Answer that was inexplicably deleted.
DateTime dt = new DateTime( Long.parseLong( "1355409000003" ) ) ;
Or, personally, I would separate onto two lines.
long millisSinceEpoch = Long.parseLong( "1355409000003" ) ;
DateTime dt = new DateTime( millisSinceEpoch ) ;
You posted this Comment to that Question:
unfortunately, the structure by which these timestamps are being consumed does not lend itself to using a different constructor - assuming I am REQUIRED to specify a string format, is there a format that parses epoch timestamps?
Again, your insistence on a constructor taking a String is nonsensical, as it is simple to the point of being trivial to wrap your textual number with a parsing call: Long.parseLong( "1355409000003" ). Don’t make a mountain out of a molehill.
java.time
The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes.
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Same approach here with java.time as seen above with Joda-Time: Parse the String to a long, and use the number to get an Instant object (rather than a DateTime object).
The java.time classes avoid constructors. So, instead of calling a constructor, call the static factory method Instant.ofEpochMilli.
long millisSinceEpoch = Long.parseLong( "1355409000003" ) ;
Instant instant = Instant.ofEpochMilli( millisSinceEpoch ) ;
Custom method
If the issue prompting your insistence is that this occurs throughout your code, and you want to avoid littering your codebase with all the extra Long.parseLong(, then you could make your own utility method to encapsulate this string-to-long conversion.
I am not recommending this as it seems like overkill. But if you insist, here is some example code.
package com.basilbourque.example;
import java.time.Instant;
public class InstantMaker
{
static public Instant parseMillis ( String countOfMillisecondsSinceEpoch )
{
// TODO - Add code to test for invalid inputs, trap for exception thrown.
long millis = Long.parseLong( countOfMillisecondsSinceEpoch );
Instant instant = Instant.ofEpochMilli( millis);
return instant;
}
// Constructor. Hide the default constructor as "private". We have no need for instances here.
private InstantMaker ( )
{
}
// `main` method for testing ad demonstration.
public static void main ( String[] args )
{
Instant instant = InstantMaker.parseMillis( "1355409000003" );
System.out.println( instant );
}
}
If this is your concern, I suggest the real problem is relying on a count-from-epoch regardless of whether it is textual or numeric. A count-from-epoch makes date-time handling much more difficult as the values cannot be discerned by humans. This makes troubleshooting, debugging, and logging tricky and unnecessarily complicated. I would suggest refactoring your code to be passing around Instant instances rather than strings like "1355409000003".
ISO 8601
If you must serialize date-time values to text, use only the standard ISO 8601 formats. That is the primary purpose for the standard, exchanging date-time values between systems. The formats are designed to be practical and sensible, easy to parse by machine yet easy to read by humans across cultures.
The java.time classes use the standard ISO 8601 formats by default when parsing/generating strings. You can see examples of such strings above in this Answer.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
Related
When I try to convert a ZonedDateTime to a Timestamp everything is fine until I call Timestamp.from() in the following code:
ZonedDateTime currentTimeUTC = ZonedDateTime.now(ZoneOffset.UTC);
currentTimeUTC = currentTimeUTC.minusSeconds(currentTimeUTC.getSecond());
currentTimeUTC = currentTimeUTC.minusNanos(currentTimeUTC.getNano());
return Timestamp.from(currentTimeUTC.toInstant());
ZonedDateTime.now(ZoneOffset.UTC); -> 2018-04-26T12:31Z
currentTimeUTC.toInstant() -> 2018-04-26T12:31:00Z
Timestamp.from(currentTimeUTC.toInstant()) -> 2018-04-26 14:31:00.0
// (with Timezone of Europe/Berlin, which is currently +2)
Why is Timestamp.from() not heeding the timezone set in the instant?
The Instant class doesn't have a timezone, it just has the values of seconds and nanoseconds since unix epoch. A Timestamp also represents that (a count from epoch).
why is the debugger displaying this with a Z behind it?
The problem is in the toString methods:
Instant.toString() converts the seconds and nanoseconds values to the corresponding date/time in UTC - hence the "Z" in the end - and I believe it was made like that for convenience (to make the API more "developer-friendly").
The javadoc for toString says:
A string representation of this instant using ISO-8601 representation.
The format used is the same as DateTimeFormatter.ISO_INSTANT.
And if we take a look at DateTimeFormatter.ISO_INSTANT javadoc:
The ISO instant formatter that formats or parses an instant in UTC, such as '2011-12-03T10:15:30Z'
As debuggers usually uses the toString method to display variables values, that explains why you see the Instant with "Z" in the end, instead of the seconds/nanoseconds values.
On the other hand, Timestamp.toString uses the JVM default timezone to convert the seconds/nanos values to a date/time string.
But the values of both Instant and Timestamp are the same. You can check that by calling the methods Instant.toEpochMilli and Timestamp.getTime, both will return the same value.
Note: instead of calling minusSeconds and minusNanos, you could use the truncatedTo method:
ZonedDateTime currentTimeUTC = ZonedDateTime.now(ZoneOffset.UTC);
currentTimeUTC = currentTimeUTC.truncatedTo(ChronoUnit.MINUTES);
This will set all fields smaller than ChronoUnit.MINUTES (in this case, the seconds and nanoseconds) to zero.
You could also use withSecond(0) and withNano(0), but in this case, I think truncatedTo is better and more straight to the point.
Note2: the java.time API's creator also made a backport for Java 6 and 7, and in the project's github issues you can see a comment about the behaviour of Instant.toString. The relevant part to this question:
If we were really hard line, the toString of an Instant would simply be the number of seconds from 1970-01-01Z. We chose not to do that, and output a more friendly toString to aid developers
That reinforces my view that the toString method was designed like this for convenience and ease to use.
Instant does not hold the Timezone information. It only holds the seconds and nanos.
To when you convert your ZonedDateTime into an Instant the information is lost.
When converting into Timestamp then the Timestamp will hold the default Timezone, which is, in your case, Europe/Berlin.
tl;dr
You are being confused by the unfortunate behavior of Timestamp::toString to apply the JVM’s current default time zone to the objects internal UTC value.
➡ Use Instant, never Timestamp.
A String such as 2018-04-26T12:31Z is in standard ISO 8601 format, with the Z being short for Zulu and meaning UTC.
Your entire block of code can be replaced with:
Instant.now()
…such as:
myPreparedStatement.setObject( … , Instant.now() ) ;
Details
The Answer by wowxts is correct. Instant is always in UTC, as is Timestamp, yet Timestamp::toString applies a time zone. This behavior is one of many poor design choices in those troubled legacy classes.
I'll add some other thoughts.
Use Instant for UTC
ZonedDateTime currentTimeUTC = ZonedDateTime.now(ZoneOffset.UTC);
While technically correct, this line is semantically wrong. If you want to represent a moment in UTC, use Instant class. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = Instant.now() ; // Capture the current moment in UTC.
Avoid legacy Timestamp class
Timestamp.from(currentTimeUTC.toInstant());
While technically correct, using my suggest above, that would be:
Timestamp.from( instant ); // Convert from modern *java.time* class to troublesome legacy date-time class using new method added to the old class.
Nothing is lost going between Instant and Timestamp, as both represent a moment in UTC with a resolution of nanoseconds. However…
No need to be using java.sql.Timestamp at all! That class is part of the troublesome old date-time classes that are now legacy. They were supplanted entirely by the java.time classes defined by JSR 310. Timestamp is replaced by Instant.
JDBC 4.2
As of JDBC 4.2 and later, you can directly exchange java.time objects with your database.
Insert/Update.
myPreparedStatement.setObject( … , instant ) ;
Retrieval.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
I have this piece of code
while(activecheck.next()){
Date status;
String vincheck;
Date curr = new Date();
int datecheck;
status = activecheck.getDate(8);
vincheck = activecheck.getString(2);
String update = "UPDATE Auctions SET status = '"+inactive+"' WHERE vin = '"+vincheck+"'";
datecheck = status.compareTo(curr);
if(datecheck < 0){
stmt6.executeUpdate(update);
}
}
Which iterates through a mysql table checking for inactive bids. I am trying to check whether the date and time listed in the sql row has been passed by the current time. However, whenever I do this, it seems to only be comparing the dates, and not the times. What could be the cause of this?
This is the format I am using : yyyy-MM-dd HH:mm:ss`
You should use type which is called Timestamp instead of the date. This way you will cover the date and the current time
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
tl;dr
if(
myResultSet.getObject( … , Instant.class ) // Retrieve `Instant` (a moment in UTC) from database using JDBC 4.2 or later.
.isBefore( Instant.now() ) // Comparing to the current moment captured in UTC.
)
{
…
}
java.util.Date versus java.sql.Date
You may be confusing this pair of unfortunately mis-named classes. The first is a date-with-time type, in UTC. The second is a date-only type. Actually the second pretends to be a date-only type but actually has a time-of-day set to 00:00:00. Even worse, the second inherits from the first, but the documentation instructs us to ignore that fact.
Confusing? Yes. These awful classes are very poorly designed. Avoid them.
java.time
You are using terribly troublesome old date-time classes that were supplanted years ago by the java.time classes.
Instant
The java.util.Date class is replaced by java.time.Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
LocalDate
The java.sql.Date class is replaced by java.time.LocalDate. The LocalDate class represents a date-only value without time-of-day and without time zone.
JDBC 4.2
As of JDBC 4.2 and later, you can directly exchange java.time classes with your database. No need to ever use java.sql or java.util date-time types again.
Tip: Make a habit of always using a PreparedStatement to avoid SQL Injection risk. Not really any more work once you get used to it.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
myPreparedStatement.setObject( … , instant ) ;
And retrieval.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
Smart objects, not dumb strings
This is the format I am using : yyyy-MM-dd HH:mm:ss`
Date-time values stored in a database do not have a “format”. Those values are stored by some internally-defined mechanism that does not concern us. They are not strings (not in any serious database, that is).
Your database, and your Java date-time objects, can parse a string representing a date-time value to create that value. And they can generate a string to represent that value. But the string and the date-time value are distinct and separate, and should not be conflated.
Use java.time objects to exchange date-time values with your database, not mere strings, just as you would for numbers and other data types your database comprehends. Use strings only for communicating textual values.
Compare
To compare your retrieved values against the current moment, use the isBefore, isAfter, and equals methods of Instant class.
Instant now = Instant.now() ;
…
Instant instant = myResultSet.getObject( … , Instant.class ) ;
boolean isPast = instant.isBefore( now ) ;
if ( isPast ) {
…
}
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
I'm trying to modify some code to use Joda-Time rather than java.sql.Timestamp
Currently the code is using Threadlocal and SimpleDateFormat:
public static final ThreadLocal<DateFormat> FORMAT_TIMESTAMP = new ThreadLocal<DateFormat>() {
#Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
}
};
public static String format(Timestamp timestamp) {
return FORMAT_TIMESTAMP.get().format(timestamp);
}
My understanding is that Joda-time is thread safe, so there is no need to use ThreadLocal
With this in mind I have modified the code to this:
public static String format(Instant timestamp) {
Instant formated = Instant.parse(timestamp.toString(), DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssXXX"));
return formated.toString();
}
If I nned to insert the values into a DB later in the code I plan to use this method.
Assuming I'm going about this the right way, is there anyway to format the DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssXXX") like the
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
At the moment I'm getting a Invalid format Exception
X is not recognised by Joda. Replacing the XXX by ZZ should do what you need.
Because DateTimeFormat is thread safe, you can share it across threads. So your code could look like this:
private static final DateTimeFormatter FORMAT_TIMESTAMP =
DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZZ");
public static String format(Instant timestamp) {
return FORMAT_TIMESTAMP.print(timestamp);
}
tl;dr
No need to define the formatting pattern for standard inputs.
Parse directly into java.time objects.
Examples…
// offset-from-UTC
OffsetDateTime.parse( "2016-01-23T12:34:56.123456789-07:00" )
…
// Z = Zulu = UTC
Instant.parse( "2016-01-23T12:34:56.123456789Z" )
…
// ISO 8601 format extended with time zone name appended in square brackets.
ZonedDateTime.parse( "2016-01-23T12:34:56.123456789-05:30[Asia/Kolkata]" )
Details
The Joda-Time project, now in maintenance mode, advises migration to java.time classes.
java.time
No need for ThreadLocal as the java.time classes are inherently thread-safe because of they are immutable objects.
The standard ISO 8601 formats for date-time values are used by default in the java.time classes. So generally no need to specify a formatting pattern for such inputs.
Instant
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
The Instant.parse method can parse standard input strings ending in Z, short for Zulu, meaning UTC.
Instant instant = Instant.parse(
"2016-01-23T12:34:56.123456789Z" );
OffsetDateTime
For standard input strings that include a specific offset-from-UTC, use the OffsetDateTime class and its parse method.
OffsetDateTime odt = OffsetDateTime.parse(
"2016-01-23T12:34:56.123456789-07:00" );
ZonedDateTime
The ZonedDateTime class with its toString method generates a String in a format that extends beyond the ISO 8601 format by appending the name in square brackets. This is wise, as a time zone is much more than an offset-from-UTC. A time zone is an offset plus a set of rules for handling anomalies such as Daylight Saving Time (DST).
This class can parse as well as generate such strings.
ZonedDateTime zdt = ZonedDateTime.parse(
"2016-01-23T12:34:56.123456789-05:30[Asia/Kolkata]" ) ;
DateTimeFormatter
For non-standard string formats, search Stack Overflow for java.time.format.DateTimeFormatter class.
Database
To send this value to a database through a JDBC driver supporting JDBC 4.2 or later, use the PreparedStatement::setObject method and for fetching, the ResultSet::getObject method.
myPreparedStatement.setObject( … , instant );
If your driver does not comply, fall back to converting to the old java.sql types. Look to the new conversion methods added to the old classes.
java.sql.Timestamp ts = java.sql.Timestamp.from( instant );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & 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. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
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.
So, basically I am trying to achieve the following format in a String:
2012-06-17T08:00:00.000+01:00
I get the original date in a string format which I then parse into different formats.
When I use SimpleDateFormat with the format as (yyyy-MM-dd'T'HH:mm:ss.sssZ), I get the following output:
2013-06-17T07:00:00.000+0530
Here +0530 should be +05:30
When I set the above date into a Calendar type and then convert it to a string I get the following format:
2013-06-17T07:00:00+05:30
Here I don't get the .000 after the seconds.
Any ideas how this can be achieved, without using JodaTime. Need manipulations in Date, String and Calendar type only
Firstly to get the extra : use XXX in your formatter like so and use Uppercase S to get the milliseconds
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
UPDATE: Above doesn't work on 1.6
Yo could try the following however
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
{
public StringBuffer format(Date date, StringBuffer toAppendTo, java.text.FieldPosition pos)
{
StringBuffer toFix = super.format(date, toAppendTo, pos);
return toFix.insert(toFix.length()-2, ':');
};
See this post for more
SimpleDateFormat pattern
"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"
tl;dr
OffsetDateTime.parse( "2012-06-17T08:00:00.000+01:00" ) // Parse string in standard ISO 8601 format to an object.
.format( // Generate a String representing the value of that `OffsetDateTime` object.
DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSXXXXX" ) // Specify a formatting pattern to force the seconds and fractional second even if zero.
) // Return a `String` object.
2012-06-17T08:00:00.000+01:00
java.time
The modern approach uses the java.time classes rather than the troublesome old legacy date-time classes. Avoid Date, Calendar, and SimpleDateFormat.
ISO 8601
Your desired format happens to be standard ISO 8601 format. The java.time classes use the standard format by default when parsing/generating strings. So no need to specify a formatting pattern.
OffsetDateTime
Your input string includes an offset-from-offset but not a time zone. So we parse as a OffsetDateTime object.
OffsetDateTime odt = OffsetDateTime.parse( "2012-06-17T08:00:00.000+01:00" ) ;
To generate a string in the same standard ISO 8601 format, simply call toString. By default, the least significant parts are omitted if zero. So no seconds or fractional second appear using your example data.
String output = odt.toString() ;
2012-06-17T08:00+01:00
If you want to force the seconds and fractional second even when zero, specify a formatting pattern.
OffsetDateTime odt = OffsetDateTime.parse( "2012-06-17T08:00:00.000+01:00" );
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSXXXXX" );
String output = odt.format( f );
2012-06-17T08:00:00.000+01:00
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
I would like to send a Java Calendar object over a web service (soap). I notice that this kind of object is too complex and there should be a better method to send the same information.
What are the basic attributes that should be sended over the web service, so the client can create a Java Calendar out of this attributes?
I'm guessing: TimeZone, Date, and Time?
Also, how can the client recreate the Calendar based on those attributes?
Thanks!
In fact I would go for Timezone tz (timezone the calendar was expressed in), Locale loc (used for data representation purpose) and long time (UTC time) if you want exactly the same object.
In most uses the time is enough though, the receiver will express it with his own timezone and locale.
I suppose the Calendar instance that you would like to send is of type java.util.GregorianCalendar. In that case, you could just use xsd:dateTime. For SOAP, Java will usually bind that to a javax.xml.datatype.XMLGregorianCalendar instance.
Translating between GregorianCalendarand XMLGregorianCalendar:
GregorianCalendar -> XMLGregorianCalendar: javax.xml.datatype.DatatypeFactory.newXMLGregorianCalendar(GregorianCalendar)
XMLGregorianCalendar -> GregorianCalendar: XMLGregorianCalendar.toGregorianCalendar()
The easiest way is to use a long value.
java.util.Calendar.getInstance().getTimeInMillis()
This returns the long value for the date. That value can be used to construct java.util.Date or a Calendar.
tl;dr
Use plain text, in UTC, in standard ISO 8601 format.
Instant.now().toString()
2018-01-23T01:23:45.123456Z
Instant.parse( "2018-01-23T01:23:45.123456Z" )
ISO 8601
The ISO 8601 standard is a well-designed practical set of textual formats for representing date-time values.
2018-01-14T03:57:05.744850Z
The java.time classes use these standard formats by default when parsing/generating strings. The ZonedDateTime class wisely extends the standard to append the name of a time zone in square brackets.
ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
String output = zdt.toString() ;
2018-01-13T19:56:26.318984-08:00[America/Los_Angeles]
java.time
The java.util.Calendar class is part of the troublesome old date-time classes bundled with the earliest versions of Java. These legacy classes are an awful mess, and should be avoided.
Now supplanted by the modern industry-leading java.time classes.
UTC
Generally best to communicate a moment using UTC rather than a particular time zone.
The standard format for a UTC moment is YYYY-MM-DDTHH:MM:SS.SSSSSSSSSZ where the T separates the year-month-day from the hour-minute-second. The Z on the end is short for Zulu and means UTC.
Instant
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = Instant.now() ;
String output = instant.toString() ;
2018-01-14T03:57:05.744850Z
If a particular time zone is crucial, use a ZonedDateTime as shown above.
Parsing
These strings in standard format can be parsed to instantiate java.time objects.
Instant instant = Instant.parse( "2018-01-14T03:57:05.744850Z" ) ;
ZonedDateTime zdt = ZonedDateTime.parse( "2018-01-13T19:56:26.318984-08:00[America/Los_Angeles]" ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time (JSR 310) classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.