回答:
私は一歩下がって、この10年前の質問を現代的に見ていきたいと思います。言及されたクラス、Date
およびXMLGregorianCalendar
は現在古いものです。私はそれらの使用に挑戦し、代替案を提供します。
Date
常にデザインが不十分で、20年以上前のものです。これは簡単です。使用しないでください。XMLGregorianCalendar
古く、昔ながらのデザインです。私が理解しているように、XMLドキュメントのXML形式で日付と時刻を生成するために使用されていました。同様2009-05-07T19:05:45.678+02:00
か2009-05-07T17:05:45.678Z
。これらの形式はISO 8601と十分に一致しており、最新のJavaの日付と時刻のAPIであるjava.timeのクラスで生成できます。多くの(ほとんど?)目的で、aの最新の置き換えはにDate
なりますInstant
。An Instant
は、(あるのと同様にDate
)ある時点です。
Instant yourInstant = // ...
System.out.println(yourInstant);
このスニペットからの出力例:
2009-05-07T17:05:45.678Z
これは、XMLGregorianCalendar
上記の例の文字列の後半と同じです。ほとんどの人が知っているように、これはInstant.toString
によって暗黙的に呼び出されたことが原因System.out.println
です。java.timeでは、多くの場合、我々は昔に我々は間で行わという変換を必要としないDate
、Calendar
、XMLGregorianCalendar
および他のクラス(私たちが必要変換を行ういくつかのケースでは、しかし、私はあなたの次のセクションでカップルを示しています) 。
a Date
もinもInstant
タイムゾーンもUTCオフセットもありません。ベンノーランドが以前に承認し、現在も最も投票数の多い回答では、JVMの現在のデフォルトのタイムゾーンを使用してのオフセットを選択していXMLGregorianCalendar
ます。最新のオブジェクトにオフセットを含めるには、を使用しOffsetDateTime
ます。例えば:
ZoneId zone = ZoneId.of("America/Asuncion");
OffsetDateTime dateTime = yourInstant.atZone(zone).toOffsetDateTime();
System.out.println(dateTime);
2009-05-07T13:05:45.678-04:00
これもXML形式に準拠しています。現在のJVMタイムゾーン設定を再度使用する場合は、に設定zone
しZoneId.systemDefault()
ます。
に変換Instant
する方法は他にもありますXMLGregorianCalendar
。それぞれの長所と短所を備えたカップルを紹介します。まず、がのXMLGregorianCalendar
ような文字列を生成するのと同じように2009-05-07T17:05:45.678Z
、そのような文字列から構築することもできます。
String dateTimeString = yourInstant.toString();
XMLGregorianCalendar date2
= DatatypeFactory.newInstance().newXMLGregorianCalendar(dateTimeString);
System.out.println(date2);
2009-05-07T17:05:45.678Z
長所:短いので、驚くことはないと思います。短所:私にとっては、インスタントを文字列にフォーマットして解析し直すのは無駄だと感じています。
ZonedDateTime dateTime = yourInstant.atZone(zone);
GregorianCalendar c = GregorianCalendar.from(dateTime);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
System.out.println(date2);
2009-05-07T13:05:45.678-04:00
プロ:それは公式の転換です。オフセットの制御は自然に起こります。短所:それはより多くのステップを経るため、より長くなります。
Date
今すぐ変更する余裕がないレガシーAPIから古いスタイルのオブジェクトを取得した場合は、次のように変換しInstant
ます。
Instant i = yourDate.toInstant();
System.out.println(i);
出力は前と同じです:
2009-05-07T17:05:45.678Z
オフセットを制御したい場合はOffsetDateTime
、上記と同じ方法でさらにに変換します。
昔ながらの方法がDate
あり、絶対に昔ながらの方法が必要な場合は、XMLGregorianCalendar
Ben Nolandの回答を使用してください。
GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
以下は、GregorianCalendarからXMLGregorianCalendarに変換するメソッドです。演習として、java.util.DateからGregorianCalendarへの変換の部分は残しておきます。
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
public class DateTest {
public static void main(final String[] args) throws Exception {
GregorianCalendar gcal = new GregorianCalendar();
XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(gcal);
System.out.println(xgcal);
}
}
編集:Slooow :-)
Joda-Timeライブラリを使用した1行の例:
XMLGregorianCalendar xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar(new DateTime().toGregorianCalendar());
承認された回答のコメントからのNicolas Mommaertsの功績。
上記の答えは私の正確なニーズを満たしていなかったので、私は以下に私のソリューションを追加すると思いました。私のXMLスキーマには、単一のDateTimeフィールドではなく、別個のDate要素とTime要素が必要でした。上記で使用されている標準のXMLGregorianCalendarコンストラクタは、DateTimeフィールドを生成します
月に1を追加する必要があるなど、いくつかのgothcaがあることに注意してください(Javaは0から月をカウントするため)。
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(yourDate);
XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH), 0);
XMLGregorianCalendar xmlTime = DatatypeFactory.newInstance().newXMLGregorianCalendarTime(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), 0);
ここでのエンコーディングが正しいことを願っています; D高速化するには、コンストラクター呼び出しの代わりにGregorianCalendarの醜いgetInstance()呼び出しを使用するだけです。
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
public class DateTest {
public static void main(final String[] args) throws Exception {
// do not forget the type cast :/
GregorianCalendar gcal = (GregorianCalendar) GregorianCalendar.getInstance();
XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(gcal);
System.out.println(xgcal);
}
}
GregorianCalendar.getInstance()
はと同等ですCalendar.getInstance()
。Calendar.getInstance()
それは同じ使用しているため、より速くそれを作ることはできませんnew GregorianCalendar()
が、それはまた、デフォルトのロケールをチェックし、代わりに、日本やBuddishカレンダーを作成することができる前に、ので、いくつかの幸運のユーザーのために、それは次のようになりますClassCastException
!
xmlをデコードまたはエンコードしてを使用していると仮定するとJAXB
、dateTimeバインディングを完全に置き換え、スキーマ内のすべての日付に「XMLGregorianCalendar」以外の何かを使用することが可能です。
JAXB
そうすることで、価値のある素晴らしいコードを書くことに時間を費やすことができると同時に、反復的なことを行うことができます。
jodatimeの例DateTime
:(java.util.Dateでこれを実行しても機能しますが、一定の制限があります。jodatimeを使用し、コードからコピーしたので、機能することがわかります...)
<jxb:globalBindings>
<jxb:javaType name="org.joda.time.LocalDateTime" xmlType="xs:dateTime"
parseMethod="test.util.JaxbConverter.parseDateTime"
printMethod="se.seb.bis.test.util.JaxbConverter.printDateTime" />
<jxb:javaType name="org.joda.time.LocalDate" xmlType="xs:date"
parseMethod="test.util.JaxbConverter.parseDate"
printMethod="test.util.JaxbConverter.printDate" />
<jxb:javaType name="org.joda.time.LocalTime" xmlType="xs:time"
parseMethod="test.util.JaxbConverter.parseTime"
printMethod="test.util.JaxbConverter.printTime" />
<jxb:serializable uid="2" />
</jxb:globalBindings>
そしてコンバータ:
public class JaxbConverter {
static final DateTimeFormatter dtf = ISODateTimeFormat.dateTimeNoMillis();
static final DateTimeFormatter df = ISODateTimeFormat.date();
static final DateTimeFormatter tf = ISODateTimeFormat.time();
public static LocalDateTime parseDateTime(String s) {
try {
if (StringUtils.trimToEmpty(s).isEmpty())
return null;
LocalDateTime r = dtf.parseLocalDateTime(s);
return r;
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static String printDateTime(LocalDateTime d) {
try {
if (d == null)
return null;
return dtf.print(d);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static LocalDate parseDate(String s) {
try {
if (StringUtils.trimToEmpty(s).isEmpty())
return null;
return df.parseLocalDate(s);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static String printDate(LocalDate d) {
try {
if (d == null)
return null;
return df.print(d);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static String printTime(LocalTime d) {
try {
if (d == null)
return null;
return tf.print(d);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static LocalTime parseTime(String s) {
try {
if (StringUtils.trimToEmpty(s).isEmpty())
return null;
return df.parseLocalTime(s);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
ここを参照してください: XmlGregorianCalendarをどのように日付で置き換えますか?
タイムゾーン+タイムスタンプに基づいてインスタントにマッピングするだけで満足し、元のタイムゾーンが実際には関係ない場合java.util.Date
は、おそらく問題ありません。
このコードをチェックしてください:-
/* Create Date Object */
Date date = new Date();
XMLGregorianCalendar xmlDate = null;
GregorianCalendar gc = new GregorianCalendar();
gc.setTime(date);
try{
xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
}
catch(Exception e){
e.printStackTrace();
}
System.out.println("XMLGregorianCalendar :- " + xmlDate);
ZonedDateTime
クラス、およびレガシークラスに追加された新しい変換メソッドを参照してください。Ole VVによるこの回答の詳細