Secret Staircase

某勉強会向け Scala スクリプト制作メモ

scala スクリプトでライブラリの依存性を解決して XML API を呼び出すということをやったのでメモ。

某勉強会の日程調整のために調整さん用の候補日を出力するスクリプトを作った。こんなのを出力する。

5/25 (土) 9:00 - 12:00
5/26 (日) 9:00 - 12:00
6/1 (土) 9:00 - 12:00
6/2 (日) 9:00 - 12:00
...

scalas

スクリプトでライブラリの依存性を解決するために scalas を使う。詳しくは sbt のドキュメントがある。conscript を使った方法ではインストールできなかったので Manual Setup の項の方法で scalas ファイルを用意した。

$HOME/bin/scalas

java -Dsbt.main.class=sbt.ScriptMain \
     -Dsbt.boot.directory=$HOME/.sbt/boot \
     -jar `dirname $0`/sbt-launch.jar "$@"

スクリプト

祝日判定にはカレンダー API を使わせていただいた。

#!/usr/bin/env scalas
// vim: ft=scala

/***
scalaVersion := "2.10.1"

libraryDependencies ++= Seq(
  "com.github.nscala-time" %% "nscala-time" % "0.4.0",
  "net.databinder.dispatch" %% "dispatch-core" % "0.10.0"
)
*/

import com.github.nscala_time.time.Imports._
import dispatch._, Defaults._

val from = LocalDate.today
val to = from + 3.months

def holidayApi(from: LocalDate, to: LocalDate) = {
  host("calendar-service.net") / "cal" <<?
    Map(
      "start_year" -> from.year.get.toString,
      "start_mon" -> from.month.get.toString,
      "end_year" -> to.year.get.toString,
      "end_mon" -> to.month.get.toString,
      "year_style" -> "normal",
      "month_style" -> "ja",
      "wday_style" -> "ja",
      "format" -> "xml",
      "holiday_only" -> "1"
    )
}

def holidays(from: LocalDate, to: LocalDate) = {
  for {
    xml <- Http(holidayApi(from, to) OK as.xml.Elem)
  } yield {
    for {
      mday <- xml \\ "mday"
      year = (mday \ "@year").text.toInt
      month = (mday \ "@month").text.toInt
      day = (mday \ "@mday").text.toInt
    } yield new LocalDate(year, month, day)
  }
}

def isHoliday(holidays: Seq[LocalDate])(day: LocalDate) =
  day.dayOfWeek.get == 6 ||
  day.dayOfWeek.get == 7 ||
  holidays.contains(day)

val hs = holidays(from, to)()

Stream.iterate(from)(_ + 1.day).
  takeWhile(_ <= to).
  filter(isHoliday(hs)).
  map(_.toString("M/d(E)") + " 9:00-12:00").
  foreach(println)

できた

...
6/29(土) 9:00-12:00
6/30(日) 9:00-12:00
7/6(土) 9:00-12:00
7/7(日) 9:00-12:00
7/13(土) 9:00-12:00
7/14(日) 9:00-12:00
7/15(月) 9:00-12:00
7/20(土) 9:00-12:00
...

手作業の方が断然速かったけどまあ良い