aboutsummaryrefslogtreecommitdiffstats
path: root/app/models/holiday.rb
blob: 13258396ab92ab60607815ef7d3094809cf4757c (plain)
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# == Schema Information
# Schema version: 114
#
# Table name: holidays
#
#  id          :integer         not null, primary key
#  day         :date
#  description :text
#

# models/holiday.rb:
#
# Store details on, and perform calculations with, public holidays on which
# the clock for answering FOI requests does not run:
#
#   ... "working day" means any day other than a Saturday, a Sunday, Christmas
#   Day, Good Friday or a day which is a bank holiday under the [1971 c. 80.]
#   Banking and Financial Dealings Act 1971 in any part of the United Kingdom.
#    -- Freedom of Information Act 2000 section 10
#
# Copyright (c) 2009 UK Citizens Online Democracy. All rights reserved.
# Email: francis@mysociety.org; WWW: http://www.mysociety.org/

class Holiday < ActiveRecord::Base

    def Holiday.holidays
        @@holidays ||= self.all.collect { |h| h.day }.to_set
    end

    def Holiday.weekend_or_holiday?(date)
        date.wday == 0 || date.wday == 6 || Holiday.holidays.include?(date)
    end

    def Holiday.due_date_from(start_date, days, type_of_days)
        case type_of_days
        when "working"
            Holiday.due_date_from_working_days(start_date, days)
        when "calendar"
            Holiday.due_date_from_calendar_days(start_date, days)
        else
            raise "Unexpected value for type_of_days: #{type_of_days}"
        end
    end

    # Calculate the date on which a request made on a given date falls due when
    # days are given in working days
    # i.e. it is due by the end of that day.
    def Holiday.due_date_from_working_days(start_date, working_days)
        # convert date/times into dates
        start_date = start_date.to_date

        # Count forward the number of working days. We start with today as "day zero". The
        # first of the full working days is the next day. We return the
        # date of the last of the number of working days.

        # This response for example of a public authority complains that we had
        # it wrong.  We didn't (even thought I changed the code for a while,
        # it's changed back now). A day is a day, our lawyer tells us.
        # http://www.whatdotheyknow.com/request/policy_regarding_body_scans#incoming-1100

        days_passed = 0
        response_required_by = start_date

        # Now step forward into each of the working days.
        while days_passed < working_days
            response_required_by += 1
            days_passed += 1 unless weekend_or_holiday?(response_required_by)
        end

        response_required_by
    end

    # Calculate the date on which a request made on a given date falls due when
    # the days are given in calendar days (rather than working days)
    # If the due date falls on a weekend or a holiday then the due date is the next
    # weekday that isn't a holiday.
    def Holiday.due_date_from_calendar_days(start_date, days)
        # convert date/times into dates
        start_date = start_date.to_date

        response_required_by = start_date + days
        while weekend_or_holiday?(response_required_by)
            response_required_by += 1
        end
        response_required_by
    end
end