きしだのはてな このページをアンテナに追加 RSSフィード

2013-09-30(月) 日経ソフトウェア11月号にFPGAの記事を書きました

日経ソフトウェア11月号にFPGAの記事を書きました 12:51 日経ソフトウェア11月号にFPGAの記事を書きましたを含むブックマーク

いま発売中の日経ソフトウェア11月号に、FPGAの記事を書きました。

入門記事といえるほど解説できてなくて、紹介程度の記事ですけど。

分量を見積もりそこねて、この3倍くらいの原稿を書いてしまっていて、それを切った貼ったになっているので、ちょっと言いたいことがぼやけてますけど、ソフトウェア技術者にとって必要なFPGA知識をなんとかまとめた感じです。

トラックバック - http://d.hatena.ne.jp/nowokay/20130930

2013-09-23(月) JavaOne2013 1日目 セッション漬け

[]JavaOne2013 1日目 セッション漬け 01:42 JavaOne2013 1日目 セッション漬けを含むブックマーク

(2013/10/15に書いてます)

さて、JavaOne初日です。

JavaOneが本気だしてきたので、たくさんのセッションがあります。

8:30から21:30くらいまで、一日中セッション漬けでした。そんな朝からほんとに出てたの?という疑問があるかもしれませんが、時差ぼけのせいか、サンフランシスコでは毎日7時に起きて23時に寝るという規則正しい生活をしていました。


セッションは、次のとおりです。

CON3638 10 Tips for Java EE 7 with PrimeFaces

CON2176“Use the Force, Luke” or Tips and Tricks for Using the Capabilities of JavaFX

CON6617 Java EE 7: What’s New in the Java EE Platform

CON6064 Introducing the Java Time API in JDK 8

CON8165 Type Inference in Java SE 8

BOF3473 The NetBeans Roadmap for Cutting-Edge Tooling for Cutting-Edge Java

BOF3433 What’s New in Java Transaction Processing

BOF4244 Swing 2 JavaFX

BOF4040 NetBeans Platform BOF


10 Tips for Java EE 7 with PrimeFaces

Java EE 7対応のPrimeFacesの話。

PrimeFacesというのは、jQueryベースのJSFコンポーネントセットです。

10のチップスということですけど、印象に残ったのは次の点。


全体的に、Bean Validationはいろいろなところで使われるようになっていて、影で支える印象です。

あと、JSFは基本的に処理をJava側で行うのですが、やはりそれでは通信ラグがあるので、クライアント側でのバリデーションも実装されたようです。


新しいコンポーネントとしては

  • オートコンプリート
  • TreeでのD&D
  • ダイアログフレームワーク
  • 固定のテーブルヘッダー
  • スクロールできるタブ

のようなものが取り上げられていました。

いままでPrimeFacesのダイアログは子ダイアログまでで、孫ダイアログを出すことができなかったのですが、これが自由に出せるようになるならとてもいいですね。


Pushフレームワークは、WebSocketやロングポーリング、JSON-Pなどを統一的に扱えるフレームワークなんだと思います。POJOをやりとりできるのでプログラムしやすそう。


Faces Flowsは、 @FlowScoped/@FlowDefinitionで一連のページ遷移でのスコープを定義するものです。


あと、FileUploadは、JSF2.2で導入された標準のFileUploadに対応したほか、HTML5を利用したコンポーネントになっているという話。


JSF2.2本体とあわせて、正常進化という感じですね。


“Use the Force, Luke” or Tips and Tricks for Using the Capabilities of JavaFX

JavaFXのセッションでも聞いておくかーということで取ってみたセッション。

CSSSVG使いましょうって話でした。

まあ、スターウォーズ人気なんだな、という感想。


Java EE 7: What’s New in the Java EE Platform

JavaEEスペックリードのリンダ・デミケルのセッション。

次のように盛りだくさんの内容。

  • JSON Processing 1.0
  • WebSocket
  • JAX-RS 2.0
  • CDI
  • Pruning
  • JMS 2.0
  • Concurrency Utilities
  • Batch
  • JPA 2.1

とりたてて新しいことを話したわけではないので、技術的詳細は省きます。


CDIはいろいろなところで当たり前に出ていたのですが、会場から「CDIって何?」という質問が出て、リンダが「Contexts and Dependency Injection」とキレ気味に答えたのが今回のハイライトです。

と、このとき冗談気味にTwitterに書いたのですが、Java EE 7全体として、これは象徴的なできごとだったのかもしれません。


Java EE 5までは、EJBがその中心的位置づけになっていました。でも、Java EE 7では明確にCDIが中心的な役割になっています。EJBが結果として単にプロモーション的な「位置づけ」だったのに対して、CDIは実際にJava EE 7での屋台骨となっています。

そして、Java EE 7の提供側では、すでにCDIが前提になっているのにかかわらず、まだ利用者にはそこまで浸透していない、ということを表す出来事でした。


あと、視力検査かってくらい文字が小さく見にくいので、会場から挙手があったにもかかわらず、華麗に無視してプレゼンを続けるリンダが印象的でした。


Introducing the Java Time API in JDK 8

JDK8で導入された、新しい日付時刻APIについて、スペックリードのStephen Colebourneのセッション。

これも特に新しい内容があったわけではないので、APIの詳細は以前のエントリなどを参考にしてください。

http://d.hatena.ne.jp/nowokay/20130917#1379376320


ステファンさんは、終始にこやかにプレゼンしていました。おだやかなガンコものという印象です。

ZonedDateTimeについて会場から、zoneIdを省略したものが欲しいという要望が出ていました。ステファンさんの答えは、LocalDateTimeを使えばいいよ、ってことでした。

あと、地域の事情で暦に変更があった場合は、JDKのアップデートで対応していく、ということでした。


セッションが終わって、上記エントリが盛り上がったときにTwitterでステファンの名前が流れまくったことについて、ぼくのブログが原因でしたごめんね、と謝っておきました。ついでに、ぼくもzoneIdを省略したものが欲しいというと、それは日本の固有の事情があるのか?と聞かれましたが、それ以上のやりとりを続ける英語力がなかったため、続きはTwitterで!と言って逃げましたw

求む英語力。


昼ビール!

会場ヒルトンホテルの横の通りをふさいで、休憩スペースになっています。

ここでは、ビール飲み放題!

f:id:nowokay:20130923144348j:image


Type Inference in Java SE 8

Java型推論の話。

Javaには型推論ないんじゃね?と思う人もいるかもしれませんが、地味に型推論はありました。

それを利用したのがJava SE 7のダイヤモンド演算子だったりします。

ただ、今までの型推論は貧弱だったので、メソッド呼び出しの引数にダイヤモンド演算子が使えないとか、同じく引数でジェネリックメソッドの呼び出しを書いたときに型推論が効かず、いちいち記述が必要とかありました。

List<String> strs = new ArrayList<>();

はできるのに

some.hoge(new ArrayList<>());

はできないので、

some.hoge(new ArrayList<String>());

と書く必要があったとか。

あと、JUnitでテストを書くときに

assertThat(myList, hasItem(Matchers.<Foo>hasProperty("hoge", is("aa"))));

とか書く必要があったのですが、ちゃんと型を省略して次のように書けるようになります。

assertThat(myList, hasItem(hasProperty("hoge", is("aa"))));

このときの型推論がJava7からJava8にどう変わったのかという話をしていたのですが、型推論の解説部分が資料の下部にあったので、ぜんぜん見えませんでした・・・

ヒルトンの会場では、資料の下のほうがぜんぜんみえません・・・


ダウンロードした資料を見直すと、「some.hoge(new ArrayList<>());」の例では、最初からnew ArrayList<Object>()を仮定して推論を始めてしまうために推論ミスになってしまうということだったようです。これをnew ArrayList<t1>()のように型変数をあてはめて推論することで最終的に正しい型にたどりつけると。


まとめとして

というのをあげていました。


The NetBeans Roadmap for Cutting-Edge Tooling for Cutting-Edge Java

NetBeansのロードマップの話

f:id:nowokay:20130923162712j:image

前日にNetBeans DayがあってNetBeansの話はたくさん聞いた人が多かったためか、人はそれほど多くありませんでした。


ロードマップはこんな感じ。

f:id:nowokay:20130923164558j:image

ざっくりしてますね。

ここでも、まずはJava8対応が目先の目標で、それからの話はそれ以降という感じ。


要望として多いのが

ということを取り上げていました。


まるでBOFのようなゆるさだなと思ったら、このセッションからはBOFだったようです。


What’s New in Java Transaction Processing

トランザクションの話。

@Transactionalアノテーションをクラスやメソッドにつけることで、宣言的トランザクションが実行できるという話。

検査例外はロールバックせず非検査例外ではロールバックするというのはEJBと同じ挙動ですが、rollbackOn、dontRollbackOnという属性で例外を指定できるというのが便利そうです。

あとは、トランザクションごとにインスタンスが生成される @TransactionScoped というスコープの紹介がありました。あまり使うことはなさそうですけど。

これで通常のアプリケーションではEJBが不要になりましたね。

でも、ここでもやはりCDIって何?という場面がありました。


大阪うどん!

なんだか大阪うどんという店があったのでよってみました。

f:id:nowokay:20130923161349j:image

お店では、ふつうに日本人の店員さんで、ふつうの日本語が通じました。

味は、高速道路のサービスエリアで食べるうどんみたいな感じです。ちょっとダシが日本のとは違うかなーくらい。ただし、量は多い。うどんはこれでmini udonです。

f:id:nowokay:20130923184748j:image

写真でみると確かにminiですが、天丼がかなり大きいです。なので、うどんも結構大きい。おなかいっぱい。


Swing 2 JavaFX

SwingプログラマJavaFXプログラマにどう移行するか、とかいう話ではなく、SwingとJavaFXの相互連携の話でした。

これまでSwingではJFXPanelを使うとJavaFXコンポーネントを使えていたのですが、JavaFXにSwingコンポーネントを載せるということができていませんでした。

それが、SwingNodeを使うとできますよ、という話。

SwingとJavaFXでは、イベントスレッドが別々なので、それをどう統合するかという話もありました。


NetBeans Platform BOF

もう完全に関係者ばかりのセッション。

f:id:nowokay:20130923205400j:image


Javaの未来はNetBeansの未来だし、NetBeansの未来はJavaの未来だ」とか豪語してましたね。

やるな。

壇上から写真とってたり、みんなリラックスしてました。

あとは、JavaFXNetBeansに載せていくって話。

このあたりは、Geeertjanのブログを見ると実際に動き出してる感じがあります。

Thanks JavaFX: WYSIWYG HTML Editor for NetBeans IDE (Geertjan’s Blog)

Improve Office Productivity with JavaFX and the NetBeans Platform (Geertjan’s Blog)


ということで、この日はここで終了。おとなしくホテルに帰って寝ました。

2013-09-22(日) JavaOne2013 0日目 キーノートとコミュニティデイ

[]JavaOne2013 0日目 キーノートとコミュニティデイ 23:04 JavaOne2013 0日目 キーノートとコミュニティデイを含むブックマーク

(2013/10/14に書いています)

JavaOne前日です。

f:id:nowokay:20130922101953j:image


前日とはいえ、テクニカルキーノートや、コミュニティ系のセッションなどが行われています。

で、ホテルでネットが使えないので、まあ10時くらいからかなーと思いながらとりあえずヒルトンへ。

ロビーがJavaOneになっています。

f:id:nowokay:20130922103658j:image

でも、ここでネットにつないで、テクニカルキーノートはMosconeであるということがわかりました・・・


Mosconeに行くときにおなかがすきすぎていたので、ラーメン的なものを。

f:id:nowokay:20130922120719j:image

結構、普通にラーメンでした。

Mosconeでは、道路をふさいでイベント会場を設営していました。

f:id:nowokay:20130922122349j:image

JavaOneは、Oracle製品全体のイベントの一部として行われていて、Mosconeでは基本的に本体であるOracle Openwordが行われます。


ストラテジー・テクニカルキーノート

ということで、全体は聞けてないんですが・・・

f:id:nowokay:20130922140826j:image

印象に残ってるのは

Java MEがJavaSEのサブセットになる、ということ

・WebSocketを使った対戦チェスゲームで、Web UI、Java FX 3D、そして3Dプリンタ出力した実物のコマを動かすロボットでのデモをみせていた

というところ。

あと、Raspberry Piと液晶タブレットを使ってJavaタブレットを作ったというのもありましたけど。

基本的には、特に新しい発表はありませんでした。


3Dプリンタ出力したチェスは、展示会場においてありました。これはかわいい。

f:id:nowokay:20130924112154j:image


UGF10369 Cool NetBeans Tips and Tricks for Java EE 7 Development

コミュニティセッションの中で「NetBeans Day」をやっていて、NetBeansのセッションがたくさんありました。でも聞けたのはこれだけ・・・

字が小さいし、声も小さいし、今回最初のセッションだしで、よく聞き取れてません・・・

目の前では、日本人の女の人が必死に睡魔と戦っていました。というか、負けてましたね。

プロファイラの話をしていて、「Swingなどのクライアントとサーバーサイドを同時にプロファイルするには?」という質問に、「それは別々にプロファイルして」というようなことを答えていました。

セッション中でも、わからないことはその場で質問します。そのとき、だまって手をあげて、気づいてもらったら話すというスタイルでした。なんかクール。


その後、PrimeFacesのデモ。

やはり声が小さくて「Can you speak louder?」という掛け声のあと、マイクを使うようになりました。マイクあったんじゃん・・・

PrimeFacesの新機能では、クライアントサイドバリデーションと、HTML5ファイルアップロードは使うかなーと思いました。

詳しいことは明日のセッション、と。

「ドラッグドロップでHTML5が作れるのはないの?」という質問に「VisualJSFってのがあったんだけど・・・」と苦笑い。それは聞いてはいけない質問やw


空き時間

16時くらいですが、この時間になると西への移動が結構きついです。太陽が正面すぎて。

f:id:nowokay:20130922180645j:image

で、ホテルの近くのパスタやによってみました。

味はまあ普通にとくにおいしくないパスタですが、量が多かった。あとで後悔することになります。

f:id:nowokay:20130922185606j:image


GlassFish Community Party

GlassFishのパーティー

会場はThirsty Bearsという、醸造所でもあるビールやさんです。ここで醸造したビールが飲めます。

地ビールとしてはそこそこの味ですが、できたてはおいしいです。

f:id:nowokay:20130922205221j:image

でも、夕方たべたパスタでビールが入らなくなっていました。不覚・・・

Javaチャンピオンっぽい人が来たり、ビリヤード楽しそうでしたが、結局日本の人とばかりしゃべってました。英会話力がほしい・・・けど、これ日本語が通じてもあまり話せなかった気がするな。


ということで、JavaOne前夜祭は終了

2013-09-21(土) JavaOne2013 -1日目

[]JavaOne2013 -1日目 02:56 JavaOne2013 -1日目を含むブックマーク

移動日です。

でかける前にうちの近所のドコモショップで携帯の機種変更などをする。時間がないのに。アホですよねーとドコモのおねえさんともりあがる。

やはり時間がかかって、結構ぎりぎり。でも、ちゃんと飛行機にのれた。

ただ、成田での乗り換えがギリギリだったので、かろうじて両替できたけどあまり買い物などする時間もありませんでした。

飛行機はとなりのおっさんのいびきがうるさかったりしたけど、とくに問題なくサンフランシスコ到着。入国審査のおっさんは機嫌が悪くてこわかった。


サンフランシスコ空港でモバイルルーターを借りたりしていると、見慣れた一団が。

ということで、桜庭さんや大山さんたちと合流。

そのまま市内に移動して各自ホテルにチェックインしたあと、港のほうに遊びにいく。

ただ、痛恨の携帯電話不携帯。ホテルに置き忘れ。カメラがないので、いろいろ面白かったのに写真がとれなかった。

子供向けの博物館とかアメリカカップの会場とか、すごく楽しかったのに。

夜は食事会の参加登録をしそびれてたので、みんなと別れてひとりでごはん。

肉うまかった。

f:id:nowokay:20130921193929j:image


ついでに、JavaOneの準備についてまとめておきます。


ホテル

4月をすぎると途端に高くなるので、2月か3月か、JavaOneの正式日程が発表されたらすぐにホテルを押さえておくほうがいいです。

キャンセルはタダなので、少しでも行く可能性があるなら、とりあえず予約しておきましょう。

場所はテンダーロイン地域をさけて、会場であるヒルトンの近くにとるといいと思います。

※追記2013/10/14 すでにもう高い・・・


荷物

つめきりとか、国内での長期移動でも必要なものは置いておいて。

ホテルの地図・住所、行き帰りの飛行機のスケジュールは印刷してもったおくほうがいいです。

飛行機の中で書く書類で、ホテル名や帰りの飛行機の便が必要だったりするのと、もし現地でネットが使えないとなると死にます。


はぶらしやひげそり、体を洗うタオルなどは用意されていないので、消耗品は自分でもって行きましょう。スリッパがあると飛行機やホテルの中で楽。

シャンプーはあるけど、せっけんもっていっておくともしホテルになくても安心。

だいたいその辺で買えるのだけど、初日に困るのが悲しい。


服装

部屋着にTシャツを持っていこうと思う人は、JavaOneで何枚かTシャツがもらえることを考慮にいれておくといいです。

基本的に寒いので、コートとはいかないまでも、寒くないジャケットが必要です。

トレジャーアイランドでイベントがあるのだけど、そのとき結構寒いので、ヒートテック的なものがあるといいと思います。

まあ、酔っ払ったら気にならないけど。


お金

3万円分を両替してもってきた。ちょうどよかったくらい。

ほとんどはカードでの支払い*1だけど、ほかの人とごはんを食べにいくと、だれかがカードをだして他の人は現金で支払うことになるので、それなりに現金が必要です。

ずっとひとりで行動するなら、現金なくても生きていけると思う。ホテルでのチップくらいか。

あと、JavaOne最終日に日本から行った人が集まってカニ会をやるので$100札を一枚用意しておく$100は別にとっておくといいです。カニ会については、JavaOneのレジストレーショントルキスタン語で「秘密のカニ会はどこですか?」って聞いたときの様子をTwitterに書いておくと、だれかがつっこんでくれると思います。

※2013/9/28 5:02(日本時間) $100札はニセ札が出回りまくったりで信用が低いので使うべきではないという指摘がありました。

2013/10/8から新札が流通を始めるようなので、来年にはそのあたりの事情は変わってるかもしれませんが、$20札5枚のほうが無難のようです。

http://www.newmoney.gov/ja.htm


ネット

あてがある人はそれぞれのネットを使うとして。

成田からの人は、成田でモバイルルータを借りておくほうがいいです。

SFの空港でのモバイルルータは高くてつながらない。高いのはいいけど、つながらないのには後悔した。*2

最初はローミングでガマンして、市内でかりたほうがよかったと思う。

ホテルの部屋で入らないので、おかげで部屋ですることがなく、早く寝るしかなくて、翌日も早く起きれた。あれ、いいことかもしれない。

JavaOne会場ではOracle無線LANが入るので、自前のwifiはなくても困らない。もちろん人が多いとOracle無線はつながらないけど、来年はもっと改善してくれるんじゃないだろうか。


英語

ぜんぜんわかんない!

まあ、お店では言いたいことをしゃべりつづければそのうちわかってもらえるので、とりあえずしゃべればおk。

セッションはまだ資料がヒントになるけど、質疑や客席間でもりあがる会話はまったくわからないので、会話に参加する英語力が欲しくなります。

あと、他の人に聞いても「英語ぜんぜんわかんない」っていうけど、あれは「テストぜんぜんできなかったわーできなかったわー」といいながらいい点とってるのと同じで、あとで他の人のブログとか見るとぜんぜんぼくより聞き取れてる様子。他の人の「英語ぜんぜんわかんない」にだまされてはいけない。

ぼくはほんとにわかってないよ!

*1:2013/10/5追記:カードの限度額にはくれぐれも注意しておきましょう

*2:2013/9/30 追記:実は高かったのは$150の紛失保証金があったからで、一週間で$100だったから高くなかった

2013-09-17(火) Java8日付時刻APIの使いづらさと凄さ

[]Java8日付時刻APIの使いづらさと凄さ 09:05 Java8日付時刻APIの使いづらさと凄さを含むブックマーク

いままでのJavaでは、日付時刻を扱おうとするとめんどくさい割に非常に低機能でした。

Java8では、新たに日付時刻APIが導入され、めんどくささが増しつつ非常に高機能になりました。

(以降、Java8で導入された日付時刻APIを単に「日付時刻API」と表します)


もちろん、慣れてきて、ちょっとしたサポートメソッドを用意してやれば、結構使いやすいのですが、それは「このAPIは使いやすい」という評価にはなりません。

つまり日付時刻APIは、慣れないとぜんぜんわからないし、サポートメソッドがないと面倒なコードが必要ということです。


いろいろあってよくわからない

日付時刻では、時点を扱うInstantや期間を扱うPeriod、時間量をあらわすDurationなど多くのクラス・インタフェースが導入されています。

これらは、IDEの補完でAPIを探りながら機能を推測すれば、それなりにドキュメントなしで使うことができます。

けど、基本の日付時刻をあらわすクラスが何通りかあって、この使い分けはカンではちょっと難しいです。


まとめるとこんな感じです。

クラス 用途 部分クラス
LocalDateTime日付時刻をあらわすLocalDate/LocalTime
OffsetDateTime時差つきの日付時刻をあらわすOffsetTime
ZonedDateTimeタイムゾーンつきの日付時刻をあらわすナシ
JapaneseDate平成・昭和など日本の暦をあらわすJapaneseDateのみ

LocalDateTimeは、時差などの情報を持たない、単に何年何月何日何時何分何秒という情報を保持します。

OffsetDateTimeと、ZonedDateTimeの違いがわかりにくいです。

OffsetDateTimeは単純に標準時からの時差がついた日付時刻を扱います。そして、ZonedDateTimeは、タイムゾーンとして指定した地域での、夏時間などの補正も含めた日付時刻を扱います。

おそらく、アプリケーションではOffsetDateTimeを使うことはなく、ZonedDateTimeを使うことになると思います。

こういった使い分けは、なかなか浸透しないのではないかと思います。


ここで問題なのは、OffsetDateTimeかZonedDateTimeなど時差情報を持ったオブジェクトを渡すべきところに、LocalDateTimeのオブジェクトを渡してしまうと、時差情報がないという実行時エラーになるというところです。

部分的に動くからLocalDateTime使ってたけど統合しようとしたら例外が出て、あとからZonedDateTimeに置き換えるということが起きそうです。また、そういったことに気づかず地雷化する事例もあるかもしれません。


あと、日付時刻APIのオブジェクトは基本immutableで、オブジェクトの内容は変わらないのですが、このことで

public LocalDateTime add3Hours(LocalDateTime ldt){
  ldt.plusHours(3);//3時間すすめる
  return ldt;
}

のように、3時間すすめたように見えるけど、実際はなんもしてない、ってことでハマる人も多そうです。


旧来のDateとの相互変換が面倒

Javaはすでに10年以上も使われているので、旧来のjava.util.Dateを使う処理が多く書かれています。

そうすると、java.util.Dateと日付時刻APIでの相互変換を行う場面が多くなるはずです。

でも、日付時刻APIでは、

Date d = new Date();
LocalDateTime ldt = new LocalDateTime(d);

のように手軽に変換することはできません。


逆に

LocalDateTime ldt = LocalDateTime.now();
Date d = ldt.toDate();

のように一発変換のメソッドもありません。


とりあえず、そもそもDateと相互変換したいときには、LocalDateTimeではなく、OffsetDateTimeかZonedDateTimeを使うほうがいいです。OffsetDateTimeはあまりアプリケーションで使わないと思うので、Dateと相互変換する場合はZonedDateTimeを使うことになるでしょう。

Dateからの変換はこのようになります。

Date d = new Date();
ZonedDateTime zdt = ZonedDateTime.ofInstant(d.toInstant(), ZoneId.systemDefault());

めんどうですね。


ZonedDateTimeの場合は、次のようにも書けます。

Date d = new Date();
ZonedDateTime zdt = d.toInstant().atZone(ZoneId.systemDefault());

ちょっと楽です。

OffsetDateTimeの場合は、atZoneメソッドではなくてatOffsetメソッドですがZoneOffsetの取得が面倒です。


APIを見てると次のように書ける気がするかもしれませんが、爆死します。

Date d = new Date();
ZonedDateTime zdt = ZonedDateTime.from(d.toInstant());

たぶん、補完みながら初めて使う人は、一度は経験することでしょう。


逆の変換は次のようになります。

Date rd = Date.from(zdt.toInstant());

LocalDateTimeからDateへの変換は、なんか血をみます。

LocalDateTime ldt = LocalDateTime.now();
Date d = Date.from(ldt.toInstant(ZoneId.systemDefault().getRules().getOffset(ldt)));

ldtが2回でてくるあたり。


一度ZonedDateTimeに変換したほうがいいでしょう。

LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date rd = Date.from(zdt.toInstant());

こんな感じで、Dateとの相互変換には慣れが必要です。引数省略したらZoneId.systemDefault()を使うようになってればいいのに。


※ 2015/7/21 追記

DateからLocalDateTimeへの変換は次のように書けます。

Date d;
LocalDateTime ldt = LocalDateTime.ofInstant(d.toInstant(), ZoneId.systemDefault());

Java8 日付時刻APIのちょっとえらいところ

タイムゾーンと時差が別れていることから推測できるように、日付時刻APIでは各地域の夏時間などの情報をもっています。

で、タイムゾーンを扱うZoneIdには、固定時差かどうかを示すフラグがあるのですが、次のようにするとfalseが表示されました。

System.out.println(ZoneId.of("Asia/Tokyo").getRules().isFixedOffset());

日本には夏時間は導入されていないので、当然trueになるかと思ったんですが、falseがでてきて、「ふぁっ?」ってなりました。

で、そういえば戦後に夏時間がどうのという話があった気がすると思って、実際にどうなってるか表示してみました。

ZoneId.of("Asia/Tokyo").getRules().getTransitions().forEach(System.out::println);

そうすると次のようになりました。

Transition[Overlap at 1888-01-01T00:18:59+09:18:59 to +09:00]
Transition[Gap at 1948-05-02T02:00+09:00 to +10:00]
Transition[Overlap at 1948-09-11T02:00+10:00 to +09:00]
Transition[Gap at 1949-04-03T02:00+09:00 to +10:00]
Transition[Overlap at 1949-09-10T02:00+10:00 to +09:00]
Transition[Gap at 1950-05-07T02:00+09:00 to +10:00]
Transition[Overlap at 1950-09-09T02:00+10:00 to +09:00]
Transition[Gap at 1951-05-06T02:00+09:00 to +10:00]
Transition[Overlap at 1951-09-08T02:00+10:00 to +09:00]

ぐぐってみると、たしかに1948年〜1951年の間、日本で夏時間が実施されていたようです。

夏時間:日本におけるサマータイム - Wikipedia


なんかえらいなーと思いました。


tz databaseを使ってるんじゃないか、という指摘がありました。タイムゾーンを管理するデータベースです。

tz database - Wikipedia

こういうのがあるんですね。

ちゃんとこのような仕組みを標準APIとして持つのは(そしてメンテナンスしていくというのは)すごいなと思いました。

btnrougebtnrouge 2013/09/17 11:38 11月のJJUG CCCでこの辺のことをしゃべる予定ですが、事前予告的な言い訳をいくつか。一応JSR 310の末席として、様々な不都合、お詫び申し上げます。

言い訳1:
Date and Time API(JSR 310)はjava.util.Dateとjava.util.Calendar系を潰すつもりで開発を始めているので、特にDateとの互換性は意図的に下げられています。Instant経由での相互変換も、ひどいことに最初期の実装には存在すらしませんでした。

言い訳2:
LocalDateTime系は時差情報を持たないので、時刻の起点が定まっていない(システム依存)という特徴があります。一方でInstantとjava.util.Dateは暗黙的にUTCという時差情報をもっており、時刻の起点が定まっています。これがLocalDateTime.toInstantなるメソッドがない理由です(実は存在していた時期もありますが…)。LocalDateTime→Date変換は、手抜きで良ければこんな感じで。

Date d = Date.from(LocalDateTime.now().atOffset(ZoneOffset.ofHours(9)).toInstant());

メソッドチェーンが使えるので、例えばLocalDate→LocalDateTime→OffsetDateTime→Dateのような変換も1行でできます。見やすいかどうかは別として。
なお、EDRの時はDateのコンストラクタにInstantを取るものが存在していました。個人的にはそちらの方が好きでした。

言い訳3:
OffsetDateTimeとZonedDateTimeの使い分けは、正直微妙です。ただ、実行効率はOffsetDateTimeの方が余計な計算をしない分だけ良好です。日本のように夏時間が存在しない地域ではOffsetDateTimeを使った方がパフォーマンスの面で有利です。
もう一つ、JSR 310対応のJAXBのカスタムマーシャラを作成する場合、XMLGregorianCalendarとの変換を実装しますが、XMLGregorianCalendarは時差情報をタイムゾーンではなくUTCからの時差で表すため、最終的にはOffsetDateTimeとの相互変換になります。LocalDateTimeやZonedDateTimeを対応させる場合は、カスタムマーシャラ内でOffsetDateTimeに変換しなければなりません。
ということで、OffsetDateTime/OffsetTimeもそれなりに使いどころはあります。OffsetDateは昨秋のJJUG CCC時点は存在したものの、気が付いたら消滅していました。

言い訳4:
JSR 310は事実上Stephen Colebourneの独裁体制で、他の人間の意見が通るのはStephenがテンパっていて周りに丸投げしたときだけ。ということでAPI全体に彼の思想というか信念というか、そういったものが染みついています。数々の不都合はその辺から来ているものです。重ね重ねお詫び申し上げます。
※ceroさんにもJSR 310のフォーマットの件で以前謝ったような…

nowokaynowokay 2013/09/17 13:24 最初はDateとの変換のできなさに、かなり絶望したのを覚えています。というか、開発中だと信じて、そのときは触るのをやめました。
そのころに比べたら使いやすくなりましたね。よく見たら、InstantにatZone/atOffsetなるメソッドもできてるし。
ZoneId.systemDefault()をデフォルトで指定してくれる便利メソッドはほしいものです。

でもまあ、そういうプログラムインタフェースはどうにかなるとして、ちょっとしたミス(慣れないと意味がわからないところ)で例外爆発しまくるのは、地雷になりそうで怖いなと思います。

nowokaynowokay 2013/09/17 13:27 OffsetDateTimeがパフォーマンスいいという話、でもパフォーマンス気になるアプリは国際展開しててZoneDateTimeが必要、国内だけ前提のものはあまりパフォーマンス気にならないというのが大多数になりそうなので、ぼくはZoneDateTimeを主流として扱おうと思っています。
というか、入門書にOffsetDateTimeとの使い分けまで書けませんw

nowokaynowokay 2013/09/17 13:29 あ、日付しか操作しない場合(Periodは使ってもDurationを使わない場合)はOffsetDateTimeでいいのか。

cero-tcero-t 2013/09/17 14:40 フォーマッタがスレッドセーフになったのは良んですいが、「yyyy/MM/dd」だと「2013/9/17」はパースできず「2013/09/17」としないとダメ。
「2013/9/16」をパースしたければ「yyyy/M/d」にしなければならず、この辺りでおそらく死人が出ます。

nowokaynowokay 2013/09/17 16:27 見える!屍が見えるぞ!ってそれバグちがうのん?w

cero-tcero-t 2013/09/17 21:04 バグって言いたくなるぐらいフォーマッタが超厳密なんですよね。たとえばSimpleDateFormatが許していた「2013/09/17aaa」みたいなのをNGにしてくれる傍らで、「MMって言ってるんだから2桁に決まってるだろJK」みたいな勢いで1桁の月をエラーにしてくるんですよね。まぁ何にせよ死人が出ますw

skirnirskirnir 2013/09/18 10:57 「2013/9/16」をパースしたければ「yyyy/M/d」にしなければならず > yyyy/M/dd なんですかね。それにしても利用者のことを全く考えていない仕様ですね…。サポートメソッド用意するか…。

xuweixuwei 2013/09/18 14:23 ここのコメント欄引用してみんなでtweetしていたら、本人からmentionが来ました。という、報告・・・ https://twitter.com/jodastephen/status/379913392883892225 まだfeedbackして変わる段階なのだろうか・・・?

nowokaynowokay 2013/09/18 14:48 わー