strptime は環境によって挙動が違う

PHP には、日付文字列をパースするための strptime という関数があります。 これを使って、Sun, 19 Apr 2015 11:43:30 GMT という文字列を %a, %d %b %Y %H:%M:%S %Z というフォーマットでパースした結果、以下の通り環境によって異なる結果になりました。 strptime は環境によって挙動が違うんですね。

OS tm_year tm_mon tm_mday tm_hour tm_min tm_sec unparsed
Linux 115 3 19 11 43 30 "GMT"
Mac 115 3 19 20 43 30 ""

Linux の場合は GMT で返ってきましたが、Mac の場合は JST で返ってきました。 (どちらも、OS のタイムゾーン設定は JST です)

どうしてこのような違いが起きたのか、ドキュメントを確認してみました。

PHP のドキュメント

ちゃんとOSにより挙動が異なることが明記されています。

注意: 内部では、 この関数はシステムの C ライブラリ関数 strptime() をコールしています。 このライブラリ関数は、OS によって挙動が異なることがあります。 PHP: strptime - Manual

ただ、どのように挙動が異なるかは記載されていません。そのため、次に各OSのドキュメントを確認してみました。

Linux の場合

フォーマットの指定として %Z (タイムゾーン) を指定することはできるが、無視すると書かれています。

原文: For reasons of symmetry, glibc tries to support for strptime() the same format characters as for strftime(3). (In most cases the corresponding fields are parsed, but no field in tm is changed.) This leads to %Z The timezone name.

日本語: 対象性のために、glibc では strptime() に strftime(3) と同じフォーマット文字をサポートさせようとしている。多くの場合、対応するフィールドが解釈されるが、tm フィールドは変更されない。使用可能なフォーマット文字を以下に示す。 %Z タイムゾーン

そのため、文字列中のタイムゾーンの指定が GMT だろうが JST だろうが、以下のように同じ結果が返ってきます。「11時って書いてあるんだから11時だろ」という解釈です。

入力 tm_year tm_mon tm_mday tm_hour tm_min tm_sec unparsed
Sun, 19 Apr 2015 11:43:30 GMT 115 3 19 11 43 30 "GMT"
Sun, 19 Apr 2015 11:43:30 JST 115 3 19 11 43 30 "JST"

Mac (BSDUNIX) の場合

現地のタイムゾーンに変換してくれるそうです。

原文: The strptime() function parses the string in the buffer buf, according to the string pointed to by format, and fills in the elements of the struc-ture structure ture pointed to by tm. The resulting values will be relative to the local time zone.

日本語: strptime() 関数は、formatが指す文字列に従ってバッファbuf内の文字列を解析し、timeptr が指す構造体の要素にあてはめます。 結果の値は現地のタイムゾーンを基準にしたものになります。

Mac OS X Manual Page For strptime(3)

ただし、文字列中のタイムゾーンとして指定できるのは GMT かローカルタイムゾーン (今回の場合は JST) のみだそうです。

原文: The %Z format specifier only accepts time zone abbreviations of the local time zone, or the value "GMT". This limitation is because of ambiguity due to of the over loading of time zone abbreviations. One such example is EST which is both Eastern Standard Time and Eastern Australia Summer Time.

日本語: %Z フォーマット指定子は、ローカルタイムゾーンタイムゾーンの省略形、または値 "GMT"のみを受け入れます。 この制限は、タイムゾーンの略語のオーバーロードによるあいまいさのためです。 そのような例の1つは、東部標準時と東オーストラリアの夏時間の両方であるESTです。

やってみると、こうなりました。「GMT の11時って書いてあるんだから、現地時間の20時だろ」という解釈です。

入力 tm_year tm_mon tm_mday tm_hour tm_min tm_sec unparsed
Sun, 19 Apr 2015 11:43:30 GMT 115 3 19 20 43 30 ""
Sun, 19 Apr 2015 11:43:30 JST 115 3 19 20 43 30 ""

OSによらず、同じ結果になるようにしたい場合は?

マニュアルに書いてありました。date_parse_from_format 関数を使いましょう。

date_parse_from_format() はこの問題の影響を受けないので、PHP 5.3.0 以降ではこちらの関数を使うことを推奨します。 PHP: strptime - Manual

まとめ

PHP は Write once, Run anywhere じゃなかった。

パラメータ設定が不適切だと、ruby-oci8 より go-oci8 の方が遅くなることもあるので要注意

こんな感じの単純な SQLRuby と Go それぞれで流したら、なぜか Go の方が遅くなりました。 特に text が長いと遅い…。

SELECT
  id
  , text
FROM
  example

使っているライブラリは、ruby-oci8, go-oci8

原因

原因は、それぞれのライブラリのパラメータのデフォルト値が異なるためでした。

ライブラリ prefetch_rows prefetch_memory
ruby-oci8 100 0
go-oci8 0 4,096

ruby-oci8 だと、メモリ使用量に関係なく 100 行をプリフェッチ。 go-oci8 だと、行数に関係なく 4,096 bytes をプリフェッチ。

なので、go-oci8 の方はメモリ使用量は安定して低いのですが、取ってくるデータが多いと何度も細かくフェッチするので遅くなります。

対策

ruby-oci8 と同じ値を接続文字列 (DSN) で設定すれば大丈夫です。 scott/tiger@localhost?prefetch_rows=100&prefetch_memory=0

もしくは、下記のドキュメントを読んでチューニングしてみるといいかも。 プリフェッチ・カウントの設定について - Oracle® Call Interfaceプログラマーズ・ガイド

JJUG CCC 2019 Spring ( #jjug_ccc ) - セッション資料の一覧

JJUG CCC 2019 Spring に行ってきました!


今回はレガシーコード改善のヒントになるネタがないかなーといろいろ話を聞いてきました。弊社の Java、古くなっているものがいくつかあって、それを少しでも楽にしたいというのがモチベーションです。
毎回思うのですが、自分が聞きたい!と思うセッションが必ずある JJUG CCC という場はすごいですね…。


あと、今回は前回よりもさらに海外勢の方が多くいらっしゃっていて、その方と懇親会でコミュニケーション取ろうとして、撃沈しまくったというのも強く印象に残っています。英語を勉強しなきゃ…!っていう強い刺激になりました。
この辺のこと、@yusuke さんがきれいにまとめていました。


今回はボランティアスタッフやったり 時間帯別セッション一覧(タイムテーブル)を勝手に作ったり*1と、少し貢献もできたかなーと思っています。
次は、登壇するぞ!? まずは Call for paper 出すところから!


さて、最後にいつものを。

今回、残念ながら満席だったり時間がかぶってしまって参加できなかったセッションもあった*2ので、あとで読むために現時点で発表者の方が公開されている資料一覧をまとめしました。*3
(あとで JJUG CCC 2019 Spring のページにもリンクが載るかもしれませんが、とりあえず自分の方で調べました)
追記:JJUGGitHub ページで公式な資料一覧が公開されました!
jjug-ccc/slides-articles-2019Spring: JJUG CCC 2019 Spring 登壇資料まとめ

10:00-10:45

12:00-12:45 (ランチセッション)

15:45-16:30

アンカンファレンス

*1:聞いてみたら、有志の方でだれかやってくれないかなー|д゚) とのことでしたw

*2:あと、今回はボランティアスタッフやっていたので、その間のセッションでも気になったのがありました。

*3:発表者のお名前は敬称略とさせていただきました。

JJUG CCC 2019 Spring のスマートフォン用タイムテーブルを作りました

5月18日(土) に開催される JJUG CCC 2019 Spring 、そのスマートフォン用タイムテーブル(セッション一覧)が欲しかったので、作りました!

JJUG CCC 2019 Spring タイムテーブル

http://yujisoftware.github.io/jjug-ccc/2019spring/#/timetable

公式ページのビルドして圧縮された Vue ファイルを手作業でハックして作ったので、本家と同じデザインになっています。 もし怒られたら消します(><)

ぜひご利用ください!!

JavaScript の String.prototype.split() の第二引数 limit は、ほかの言語と意味が違う

JavaScript の split メソッドを使ったら「あれ?」となったのでメモ。

一般的な spilt メソッド

Java, C#, Ruby, Perlsplit メソッドは、第二引数に limit を指定できます。 これを指定すると分割回数が制限されます。
(下記の例だと、文字列を2つに分割しています)

Java
"aaa,bbb,ccc".split(",", 2)
// ==> String[2] { "aaa", "bbb,ccc" }
C#
"aaa,bbb,ccc".Split(new char[]{','}, 2)
// ==> String[2]{ "aaa", "bbb,ccc" }
Ruby
"aaa,bbb,ccc".split(",", 2)
# ==> ["aaa", "bbb,ccc"]
Perl
split(/,/, "aaa,bbb,ccc", 2)
# ==> ("aaa", "bbb,ccc")

JavaScript の spilt メソッド

JavaScriptsplit メソッドも、第二引数に limit を指定できます。 ただ、ほかの言語と意味が違っていて、これを指定すると戻り値の要素数が制限されます。
(下記の例だと、文字列を分割して最初の2つを返しています)

JavaScript
"aaa,bbb,ccc".split(",", 2)
// ==> Array [ "aaa", "bbb" ]

MDN には「見つかった分割結果の数の制限を指定する整数です。」と書かれています。
パッと読んだ感じほかの言語と同じかなっと思ったんですが、よく考えると違ったという…。

お気を付けください!

意地でも IE を使わずに Firefox をダウンロードする方法

新しい Windows 7 の PC を使おうとしたら Internet Explorer (IE) しか入っていませんでした。
しかし、私は IE が嫌いなので、Firefox を使いたいです。

そこで、Firefox ダウンロードしようと思い…、そこで気づきました。
Windows 7Firefox を使おうとしたら、まず最初に IE を起動しなくてはいけません。

しかし、私 は I E が 大 嫌 い で す。

そこで、Windows の機能だけで Firefox をダウンロードする方法を編み出してみました。

IE を使わずに Firefox をダウンロードする

  1. 「ファイル名を指定して実行」を開く
  2. 「参照」ボタンをクリック
  3. ファイル名欄に https://mzl.la/2inJu0a と入力1して、「開く」ボタンをクリック
    f:id:chiheisen:20190220011642p:plain
  4. 「ファイル名を指定して実行」の名前欄に C:\Users\… で始まるパスが入っているので、その前後に文字を付け加えます。
    cmd /c move "(入力されたパス)" "(移動先のパス)\Firefox.exe"
    f:id:chiheisen:20190220011717p:plain
  5. 「OK」ボタンをクリック

これで、Firefox をインストールできるようになりました!! f:id:chiheisen:20190220011719p:plain

なにやってるの?

ファイルを開くダイアログには「URLからファイルをダウンロードして開く」という機能があります。それを使って、インストーラをダウンロードしました。
ただ、そのままだとファイルに拡張子がつかないので実行できません。
そこで、最後にファイルを移動しつつ拡張子を付けています。

これで、IE を使わずに済みますね!2

豆知識

https://bit.ly/firefox へアクセスすると IE のページに飛びます。


  1. https://download.mozilla.org/?product=firefox-latest&os=win&lang=ja への短縮URL

  2. Windows 10 なら、curl が使えるのでもっと簡単に Firefox をダウンロードできます。

JJUG CCC 2018 Fall( #jjug_ccc ) - セッション資料の一覧

JJUG CCC 2018 Fall に行ってきました!

今回、興味のあるディープな JVM の話とかアーキテクチャ設計をたくさん聞けて、個人的にはとてもテンションが上がりました!
「Deep dive into instanceof」のように、HotSpot VM の深い話を知れたり。仕事で役に立つわけではないですが、完全に趣味として、こういう話を聞けるのはとても好きで楽しいです。
一方で、アーキテクチャ系の話もいろいろ聞けて、こちらは仕事で生かせそうです。最近、うまく設計できなくて四苦八苦していたことが続いていたのですが、その解決に向けてのヒントになりました。

この幅広さとバランスが JJUG CCC のいいところだと思います!


さて、最後にいつものを。

今回、残念ながら満席だったり時間がかぶってしまって参加できなかったセッションもあったので、あとで読むために現時点で発表者の方が公開されている資料一覧をまとめしました。*1
(あとで JJUG CCC 2018 Fall のページにもリンクが載るかもしれませんが、とりあえず自分の方で調べました)
追記:JJUGGitHub ページで公式な資料一覧が公開されました!
jjug-ccc/slides-articles-2018Fall: JJUG CCC 2018 Fall 登壇資料まとめ

10:00-10:45

11:00-11:45

12:00-12:45(ランチセッション)

13:30-14:15

14:30-15:15

17:45-18:30

*1:発表者のお名前は敬称略とさせていただきました。