+n month の罠

PHP Advent Calendar 2013 - Qiita の 23 日目です。
strtotime の話をします。

+n month の罠

日時を扱うのは大抵どの言語でも難しいです。PHPでももちろんそう。

PHP で日付の足し算をするのには strtotime を使います。

echo date('Y-m-d', strtotime('2013-01-31 +1 day')) . PHP_EOL; //=> 2013-02-01

strtotime はすごく便利ですが、うかつに月の計算をすると予期しない結果が返ってきます。

echo date('Y-m-d', strtotime('2013-01-31 +1 month')) . PHP_EOL; //=> 2013-03-03
echo date('Y-m-d', strtotime('2013-02-28 +1 month')) . PHP_EOL; //=> 2013-03-28
echo date('Y-m-d', strtotime('2013-03-31 +1 month')) . PHP_EOL; //=> 2013-05-01

1月の1ヶ月後が3月、3月の1ヶ月後が5月になっています。これは一体。。。

nヶ月後っていつなのか

冷静に考えてみると、月の日数って月によって違うし、nヶ月後の日付って人間の意思なしには決められないものなんですね。
1月31日の1ヶ月後はいつなのか、30日後にしたいとき、31日後にしたいとき、2月の月末にしたいとき、いろいろあると思います。

ちゃんと +n month する

この +n month の罠にハマらないために、n月 +1 month が n+1 月となることを期待して +n month するときは月初を起点にすることを心がけましょう。

echo date('Y-m-d', strtotime('2013-01-01 +3 month')) . PHP_EOL; //=> 2013-02-01
echo date('Y-m-d', strtotime('2013-02-01 +3 month')) . PHP_EOL; //=> 2013-03-01
echo date('Y-m-d', strtotime('2013-03-01 +3 month')) . PHP_EOL; //=> 2013-04-01


なぜ、これだとうまくいくのか。PHP は +1 month するとき、現在月の日数を足し算するからです。うるう年とかも考慮されてるのでご安心を。

echo date('Y-m-d', strtotime('2013-01-31 +1 month')) . PHP_EOL; //=> 2013-03-03
echo date('Y-m-d', strtotime('2013-02-28 +1 month')) . PHP_EOL; //=> 2013-03-28
echo date('Y-m-d', strtotime('2013-03-31 +1 month')) . PHP_EOL; //=> 2013-05-01
echo date('Y-m-d', strtotime('2013-01-31 +31 day')) . PHP_EOL; //=> 2013-03-03
echo date('Y-m-d', strtotime('2013-02-28 +28 day')) . PHP_EOL; //=> 2013-03-28
echo date('Y-m-d', strtotime('2013-03-31 +31 day')) . PHP_EOL; //=> 2013-05-01


とまあこの件に関しては PHP の仕様がおかしいとはあまり思わないんですが、にしても PHP の日付・時刻周りはひどすぎですね。なんか使いやすいライブラリないのかな。

sbt-native-packager でお手軽に Scala アプリケーションの deb, rpm, zip を作成する

Scala Advent Calendar 13 日目の記事です。


sbt-native-packager の紹介をします。


https://github.com/sbt/sbt-native-packager
http://www.scala-sbt.org/sbt-native-packager/

sbt-native-packager とは

rpm, deb, universal(zip) パッケージが簡単に作れる sbt プラグインです。

サンプルアプリ

実際にいじってみましょう。
Hello というだけの簡単なアプリをパッケージングしてみます。

// src/main/scala/example/Hello.scala
package example

object Hello {
  def main(args: Array[String]): Unit = {
    println("Hello! Scala.")
  }
}

設定

sbt の設定はこんな感じ。特に難しくはないでしょう。

// project/plugins.sbt
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "0.6.4")
// build.sbt
import com.typesafe.sbt.SbtNativePackager._
import com.typesafe.sbt.packager.Keys._

packageArchetype.java_application

name := "hello"

packageDescription := "hello"

maintainer := "tototoshi"

Debian パッケージを作成する

Debian パッケージは debian:packageBin コマンドで作成できます。
いくつか依存しているコマンドがあるようなので(fakeroot とか)怒られたら適宜インストールしてください。

> debian:packageBin

これで target/hello-0.1.0.deb ができるのでインストールしてみます。

> sudo dpkg -i target/hello-0.1.0.deb
$ hello
Hello! Scala.

めでたし。
rpm は試してないけど rpm:packageBin を使えば出来るそうです。

zip アーカイブを作成する

Mac, Windows 向けには zip アーカイブ(universal パッケージ)で配布します。

> universal:packageBin

このコマンドで target/universal/hello-0.1.0.zip ができます。


展開すると bin, lib というディレクトリができていることがわかります。
./bin/hello は sbt-native-packager が勝手に作ってくれた起動スクリプトです。
./bin/hello.bat もあるので Windows でも使えますね。sbt-start-script は Windows基本的に無視だったので Windows 派はこれだけでうれしいですね。

├── bin
│ ├── hello
│ └── hello.bat
└── lib
    ├── hello.hello-0.1.0.jar
    └── org.scala-lang.scala-library-2.10.2.jar

以上、sbt-native-packager の紹介でした。
sbt-start-script の後継として位置づけされているようなので、sbt-start-script を使っている方は乗り換えを検討してみてください。

アルパカの話をしました @ 怖いScala

怖いScala(http://connpass.com/event/4112/) で自作のブラウザ操作用簡易言語 alpaca の紹介をしてみました。
ブラウザを使った自動テストをしたいけどいろいろしんどいので挫折して、もう手動テストを高速に行うで妥協しよう、となったときの産物です。


http://tototoshi.github.io/slides/kwi-scala-alpaca-life/


作ってみたら最終的に文法がどうみてもcapybaraですな感じになりました。
なのでもう別にcapybaraでいいんじゃないかな!
でもcapybara以上に手軽に使えるので個人的にはかなり重宝しています。


こういうのを作るのもScalaでやるとお手軽で良いですね(いい話)ってことで、よろしくお願いします。

PHPer はじめました 【2年ぶり 2度目】

xuwei_k にこんなこと言われてしまったので世の中が厳しい話をします。

この 2 年くらいは Java とか Scala とか Ruby とか Python とか bash とか awk とかちょっと Perl とか書いてたんですが、転職して今週から PHP を書いてます。PHPStorm 買いました。(サムライズムさんあざーす)
ちなみに前前職では PHP とか Python とか Java でしたし、まあいろいろですね。


Scala ではなく PHP であることに関して、特に不満はないというか、面接のときも Scala 書きたいですとか、Scala 書かせますみたいな話はいっさいしてなくて、「嫌いな食べ物は?」「え...ブロッコリーです」みたいな感じでしたので



こういうわけではないです。


最近は Scala の仕事もちらほら聞くけれど、なんで Scala で転職しなかったかというと Scala に限らず自分にとって魅力的な仕事を見つけるのは難しいというそれだけです。まあ Scala 書きたい欲みたいなものは趣味でいろいろ書いて十分発散してるので別にいいかなって感じです。


実際 PHP がだめかと言うと、好きで書く言語ではないと思いますし、いまいち感はあるけれど仕事の道具としては悪くはないと思っています。ここは意見が分かれるところだし、それについて議論するのはまずアルコールが入ったほうが楽しいです。


ちなみに前職を退職した理由については、やめた人がなに言っても説得力ないのでノーコメントですが、Scala が書きたい人がいたら紹介します。転職先がどこなのかは言っていいのかよくわかんないので言いませんが、PHP が書きたい人がいたら(ry


プログラマ各位においては、仕事の不満とか人生の辛さとか世の中の厳しさとか、そういうものを PHP にぶつけないようお気をつけください。同僚が PHP を dis っていたら「そんな事言わせちゃってごめんな」と抱きしめてあげてください。いいですか、Scala 書こうが PHP 書こうが世の中は厳しいのです。

Mac でファイルの変更を検知する

Linux の inotify 的なものが Mac にはないけれど、OS XAPI を使えばできるらしい。で、それをお手軽に叩けるようにしたのが fswatch。

https://github.com/alandipert/fswatch

インストール

$ brew install fswatch

使い方

$ fswatch-run [監視対象のパス] [実行スクリプト]

その他の方法

  • launchd
  • jnotify
  • etc