Prev / Next

2005-10-14 / Rubyのプログラムで今月「日曜日」が何回あるのか教えてください。

http://www.hatena.ne.jp/1129120181


t = Time.now.localtime
yd = Time.local(t.year, 12, 31).yday
if yd == 365 and t.mon == 2 then # Uruu ja nai toshi 2-gatsu
  answer = 4
else
  t2 = Time.local(t.year, t.mon, 1)
  if yd == 366 and t.mon == 2 then # Uruu doshi 2-gatsu
    if t2.wday == 0 then answer = 5
    else answer = 4
    end
  else if [4,6,9,11].include?(t.mon) then # Shou no tsuki
         if t2.wday == 0 or t2.wday == 6 then answer = 5
         else answer = 4
         end
       else # Dai no tsuki
         if [0,6,5].include?(t2.wday) then answer = 5
         else answer = 4
         end
       end
  end
end
p t,answer


まず閏年でないときの2月は必ずどの曜日も4回なので先に除外。
閏年の2月は1日が日曜日のときだけ日曜日が5回。
残りの小の月(4,6,9,11)の場合は1日が土曜か日曜の場合のみ5回日曜がある。
大の月の場合は1日が金・土・日の場合だけ5回日曜がある。
なんかwdayの処理あたりがださいか。


Date を使う(1)

require ”date”
d = Date.today
d -= d.day - 1;
p((d...(d>>1)).find_all {|i| i.wday.zero?}.size)
# => 5



Date を使う(2)

require ’date’

d = Date.new(Date.today.year, Date.today.mon, 1)
ans = 0
d.upto((d >> 1) - 1){|dd| if dd.wday == 0 then ans = ans+1 end }
p ans


その月の1日と最後の日までをなめて日曜ならansをカウントアップ


Date を使う(3)
#今月一日の曜日と、今月が何日まであるかで決まってしまうので最初に配列を作ってしまいます……。

require ’date’

sundays = Array.new
sundays[28] = [4,4,4,4,4,4,4]
sundays[29] = [5,4,4,4,4,4,4]
sundays[30] = [5,4,4,4,4,4,5]
sundays[31] = [5,4,4,4,4,5,5]

d = Date.today
y = d.year
m = d.mon

#一日の曜日
first = Date.new(y, m, 1).wday

#次の月の一日の前の日=今月の最後の日=今月の日数
#12月なら次の年の1月ということで
last = (Date.new(y + (m == 12 ? 1 : 0), (m == 12 ? 1 : m + 1), 1) - 1).day

p sundays[last][first]
__END__


無駄なサイズの配列を作っているので、

sundays[0] = [4,4,4,4,4,4,4]
sundays[1] = [5,4,4,4,4,4,4]
sundays[2] = [5,4,4,4,4,4,5]
sundays[3] = [5,4,4,4,4,5,5]
:
:
p sundays[last-28][first]


が正当でしょうけど。


Date を使う(4)
歴週を使ってみました。少しトリッキーですが、ちゃんと動作すると思います。
コメントを外すとコマンドラインから任意の年と月が指定できます。

require ’date’
first_day = Date.new(Date.today.year,Date.today.mon)
#first_day = Date.new(ARGV.shift.to_i,ARGV.shift.to_i) if ARGV.size == 2
p (53 + (first_day >> 1).cweek - first_day.cweek) % 53



Date を使う(5)

require ’date’
d=Date.today
d-=d.day-1
p ((d>>1)-d+d.cwday-1).to_i/7


今月の日数を7で割るのが基本的なアイデアです。
月の最初の曜日に応じて適当に補正しています。


Date を使う(6)
今度はRubyで。

def countSundays(m,y)
  require’date’;d=Date.new(y,m);(d.cwday+((d>>1)-1).day-1)/7
end


上の方も「今月一日の曜日と、今月が何日まであるかで決まってしまう」
と言われていますが、同じ考え方です。

(1) Date#cwdayメソッドで月初の曜日を算出
(2) その値に今月の日数-1を加算
(3) (2)を7で割って商(整数)を算出

Date#cwdayメソッドの返す値の仕様(1-7,日曜=7)から、
(2)の値を7で割り切れる整数の数=日曜日の回数だと考えます。


web 上カレンダーを利用

require ’open-uri’
puts open(’http://d.hatena.ne.jp/sample/’).read.scan(%r{<tr>¥r?¥n.+?class=”calendar-day”>(¥d+)</td>}).size


こんなんどうでしょう。
すでにある資産(web上のカレンダー)を活用します。


一般化
http://www.rubyist.net/~nobu/t/20051013.html#p01
「今月」と「日曜日」を一般化するとこうかな。

require 'date'

class Date
  def count_wdays(w)
    last = (self.class.new(year, month) >> 1) - 1
    (last.day + (w - last.wday - 1) % 7) / 7
  end
end



Python

from datetime import date
import calendar
today = date.today()
answer = 0
for i in calendar.monthcalendar(today.year, today.month):
if i[6]: answer += 1

print answer


pythonのcalendar.monthcalendarは、1週間ごとの日付の配列を1ヶ月分返します。
例えば、今月なら、[[0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0]]
こんな感じ。forで1週間ごと取り出して、6番めの値が0以外なら、
日曜が存在するので1加算する、といった方法で求めています。


Perl

$ perl -MCalendar::Simple -e ’print scalar grep { $_->[0] } calendar;’



Shell

bash-3.00$ cal | cut -b 1-2 | grep -c [0-9]
5



via: A Strolling Programmer (2005-10-13)
     http://www.rubyist.net/~nobu/t/20051013.html#p01

comments powered by Disqus