Comment detail

年間カレンダー (Nested Flatten)
「車輪の再発明」の誹りは免れませんが、Shell Scriptで書いてみました。

Bourne Shellでも動作するように書いたので、Unix系OSなら大半で動作すると思います。
時間のある時に AIX, HP-UX, Linux, Solaris などで動作確認してみます。

# 手元のCygwinで動作することを確認しました。

以下のワンライナーを実行することで、「年間カレンダー」を表示することが可能です。

  e.g.
    $ for i in `seq 1 12`; do ./cal.sh $i 2008; done
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/bin/sh

case "`echo -e`" in
  -e) echo_() { echo    "$@"; };;
   *) echo_() { echo -e "$@"; };;
esac

case "`echo_ '\r'`" in
  '\r') case "`(print X) 2>/dev/null`" in
          X) echo_() { print "$@"; };;
          *) PATH=/usr/5bin:$PATH; export PATH;;
        esac
        ;;
esac

is_numeric() { return `echo_ $1 | grep -E '^[0-9]+$' >/dev/null 2>&1`; }

dow() {
  y=$1; m=$2
  [ $2 -le 2 ] && { y=`expr $y - 1`; m=`expr $m + 12`; }
  expr \( 5 \* $y / 4 - $y / 100 + $y / 400 + \( 26 \* $m + 16 \) / 10 + $3 \) % 7
}

eom() {
  case $2 in
    1|3|5|7|8|10|12) echo_ 31;;
           4|6|9|11) echo_ 30;;
                  2) is_leap_year $1 && echo_ 29 || echo_ 28;;
  esac
}

is_leap_year() {
  [ `expr $1 % 400` -eq 0 ] && return 0
  [ `expr $1 % 100` -eq 0 ] && return 1
  [ `expr $1 %   4` -eq 0 ] && return 0
  return 1
}

main() {
  [ $# -ne 2 ] && { echo_ "usage: $0 [month] [year]"; return 1; }

  is_numeric $1 || return 1; [ $1 -lt 1 -o $1 -gt   12 ] && return 1
  is_numeric $2 || return 1; [ $2 -lt 1 -o $2 -gt 9999 ] && return 1

  w=`dow $2 $1 1`
  d=`eom $2 $1`

  echo_ "$2/\c"; [ `echo_ "$1\c" | wc -m` -eq 1 ] && echo_ ' \c'; echo_ "$1"
  echo_ 'Su Mo Tu We Th Fr Sa'
  for i in `seq 1 $w`; do echo_ '   \c'; done
  for i in `seq 1 $d`; do
    [ `echo_ "$i\c" | wc -m` -eq 1 ] && echo_ ' \c'
    echo_ "$i\c"
    [ `dow $2 $1 $i` -eq 6 ] && echo_ '' || echo_ ' \c'
  done
  echo_ '\n'

  return 0
}

main $*
ANSIカラーに対応してみました。

# ダム端末ではエスケープシーケンスがそのまま表示されるため、レイアウトが崩れます。

  e.g.
    53,54c54,59
    <     echo_ "$i\c"
    <     [ `dow $2 $1 $i` -eq 6 ] && echo_ '' || echo_ ' \c'
    ---
    >     case "`dow $2 $1 $i`" in
    >       0) echo_ "\033[31m$i\033[m \c";;
    >       6) echo_ "\033[34m$i\033[m"   ;;
    >       *) echo_ "$i \c"              ;;
    >     esac
いくつかのUnix系OSでは正常に動作しなかったので、若干修正しました。

以下のOSで動作を確認。

  AIX     (5.2, 5.3)
  HP-UX   (11.00, 11.11, 11.23)
  Linux   (2.2, 2.4, 2.6)
  Solaris (5.5, 5.6, 5.7, 5.9, 5.10)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#!/bin/sh

case "`echo -e`" in
  -e) echo_() { echo    "$@"; };;
   *) echo_() { echo -e "$@"; };;
esac

case "`echo_ '\r'`" in
  '\r') case "`(print X) 2>/dev/null`" in
          X) echo_() { print "$@"; };;
          *) PATH=/usr/5bin:$PATH; export PATH;;
        esac
        ;;
esac

(echo '' | grep -E '' >/dev/null 2>&1) && grep_() { grep "$@"; } || grep_() { /usr/xpg4/bin/grep "$@"; }

seq_() { i=$1; while [ $i -le $2 ]; do echo_ "$i \c"; i=`expr $i + 1`; done; }

is_numeric() { return `echo_ $1 | grep_ -E '^[0-9]+$' >/dev/null 2>&1`; }

dow() {
  y=$1; m=$2
  [ $2 -le 2 ] && { y=`expr $y - 1`; m=`expr $m + 12`; }
  expr \( 5 \* $y / 4 - $y / 100 + $y / 400 + \( 26 \* $m + 16 \) / 10 + $3 \) % 7
}

eom() {
  case $2 in
    1|3|5|7|8|10|12) echo_ 31;;
           4|6|9|11) echo_ 30;;
                  2) is_leap_year $1 && echo_ 29 || echo_ 28;;
  esac
}

is_leap_year() {
  [ `expr $1 % 400` -eq 0 ] && return 0
  [ `expr $1 % 100` -eq 0 ] && return 1
  [ `expr $1 %   4` -eq 0 ] && return 0
  return 1
}

main() {
  [ $# -ne 2 ] && { echo_ "usage: $0 [month] [year]"; return 1; }

  is_numeric $1 || return 1; [ $1 -lt 1 -o $1 -gt   12 ] && return 1
  is_numeric $2 || return 1; [ $2 -lt 1 -o $2 -gt 9999 ] && return 1

  w=`dow $2 $1 1`
  d=`eom $2 $1`

  echo_ "$2/\c"; [ `echo_ "$1\c" | wc -c` -eq 1 ] && echo_ ' \c'; echo_ "$1"
  echo_ 'Su Mo Tu We Th Fr Sa'
  for i in `seq_ 1 $w`; do echo_ '   \c'; done
  for i in `seq_ 1 $d`; do
    [ `echo_ "$i\c" | wc -c` -eq 1 ] && echo_ ' \c'
    case "`dow $2 $1 $i`" in
      0) echo_ "\033[31m$i\033[m \c";;
      6) echo_ "\033[34m$i\033[m"   ;;
      *) echo_ "$i \c"              ;;
    esac
  done
  echo_ '\n'

  return 0
}

main $*

Index

Feed

Other

Link

Pathtraq

loading...