3 class Date
We use a naive definition of a sitting day: this includes a calendar day when the Commons sits, together with following calendar days if the Commons sat through the night.
For example: if the Commons sat on a Tuesday and continued to sit overnight into Wednesday, both Tuesday and Wednesday would count as actual sitting days.
If the Tuesday sitting lasted long enough to overlap the starting time of the Wednesday sitting, the Tuesday would be a parliamentary sitting day, but the Wednesday would not.
15 def is_commons_actual_sitting_day?
16 SittingDay.all.where( 'start_date <= ?', self ).where( 'end_date >= ?', self ).where( house_id: 1 ).first
17 end
We use a naive definition of a sitting day: this includes a calendar day when the Lords sits, together with following calendar days if the Lords sat through the night.
For example: if the Lords sat on a Tuesday and continued to sit overnight into Wednesday, both Tuesday and Wednesday would count as actual sitting days.
If the Tuesday sitting lasted long enough to overlap the starting time of the Wednesday sitting, the Tuesday would be a parliamentary sitting day, but the Wednesday would not.
27 def is_lords_actual_sitting_day?
28 SittingDay.all.where( 'start_date <= ?', self ).where( 'end_date >= ?', self ).where( house_id: 2 ).first
29 end
We use a more strict definition of a sitting day. We don’t include dates for which the Commons continued sitting from a previous day, where the preceding day’s sitting overlapped with the next day’s programmed sitting.
35 def is_commons_parliamentary_sitting_day?
36 SittingDay.all.where( 'start_date = ?', self ).where( house_id: 1 ).first
37 end
We use a more strict definition of a sitting day. We don’t include dates for which the Lords continued sitting from a previous day, where the preceding day’s sitting overlapped with the next day’s programmed sitting.
43 def is_lords_parliamentary_sitting_day?
44 SittingDay.all.where( 'start_date = ?', self ).where( house_id: 2 ).first
45 end
This is a day where all Members of the House sit ‘digitally’, rather than physically.
A virtual sitting may continue over more than one calendar day. We count any continuation, where the preceding day’s sitting overlapped with the next day’s programmed sitting, as also being a virtual sitting day.
As of the end of June 2020, the Commons has had no virtual sitting days.
55 def is_commons_virtual_sitting_day?
56 VirtualSittingDay.all.where( 'start_date <= ?', self ).where( 'end_date >= ?', self ).where( house_id: 1 ).first
57 end
This is a day where all Members of the House sit ‘digitally’, rather than physically.
A virtual sitting may continue over more than one calendar day. We count any continuation, where the preceding day’s sitting overlapped with the next day’s programmed sitting, as also being a virtual sitting day.
65 def is_lords_virtual_sitting_day?
66 VirtualSittingDay.all.where( 'start_date <= ?', self ).where( 'end_date >= ?', self ).where( house_id: 2 ).first
67 end
71 def is_either_house_actual_sitting_day?
72 self.is_commons_actual_sitting_day? or self.is_lords_actual_sitting_day?
73 end
77 def is_joint_actual_sitting_day?
78 self.is_commons_actual_sitting_day? and self.is_lords_actual_sitting_day?
79 end
83 def is_either_house_parliamentary_sitting_day?
84 self.is_commons_parliamentary_sitting_day? or self.is_lords_parliamentary_sitting_day?
85 end
89 def is_joint_parliamentary_sitting_day?
90 self.is_commons_parliamentary_sitting_day? and self.is_lords_parliamentary_sitting_day?
91 end
95 def is_adjournment_day?
96 AdjournmentDay.all.where( 'date = ?', self ).first
97 end
101 def is_commons_adjournment_day?
102 AdjournmentDay.all.where( 'date = ?', self ).where( house_id: 1 ).first
103 end
107 def is_lords_adjournment_day?
108 AdjournmentDay.all.where( 'date = ?', self ).where( house_id: 2 ).first
109 end
113 def is_prorogation_day?
114 ProrogationDay.all.where( 'date = ?', self ).first
115 end
119 def is_dissolution_day?
120 DissolutionDay.all.where( 'date = ?', self ).first
121 end
That may be an actual sitting day - including parliamentary sitting days, a virtual sitting day, an adjournment day, a day within prorogation or a day within dissolution.
127 def is_calendar_populated?
128 self.is_commons_actual_sitting_day? or self.is_lords_actual_sitting_day? or self.is_commons_virtual_sitting_day? or self.is_lords_virtual_sitting_day? or self.is_adjournment_day? or self.is_prorogation_day? or self.is_dissolution_day?
129 end
We use this to check if we've run out of calendar
so we don't keep cycling into future days and loop infinitely.
This is our event horizon.
137 def is_calendar_not_populated?
138 !self.is_calendar_populated?
139 end
In guidance issued on 16-04-2020 the Lords Procedure Committee stated, A Virtual Proceeding is not a sitting of the House.
Whilst clerks state that a virtual sitting day does not count as a sitting day for the purposes of calculating scrutiny periods, lawyers imply this would need to be tested in court.
Unless and until this is resolved, these methods use the clerks' definition of non-sitting scrutiny day.
During a short adjournment, adjournment days count toward the scrutiny period.
This method allows the definition of a “short” adjournment to be adjusted by passing in a maximum day count.
In all known cases “short” is defined as not more than four days.
For the purposes of calculating non-sitting scrutiny days, virtual sitting days also count.
159 def is_commons_non_sitting_scrutiny_day?( maximum_day_count )
163 if self.is_commons_adjournment_day? or self.is_commons_virtual_sitting_day?
Having found that this is a Commons adjournnment day or a Commons virtual sitting day, we start the adjournment day count at 1.
167 non_sitting_scrutiny_day_count = 1
We want to cycle through the following days until we reach the maximum day count passed into this function.
171 date = self
172 for i in ( 1..maximum_day_count )
Go forward one day.
176 date = date.next_day
If this is a Commons adjournnment day or a Commons virtual sitting day ...
179 if date.is_commons_adjournment_day? or date.is_commons_virtual_sitting_day?
... add one to the non-sitting scrutiny day count.
182 non_sitting_scrutiny_day_count +=1
If this is not a Commons adjournnment day or a Commons virtual sitting day ...
185 else
... stop cycling through following days.
188 break
189 end
190 end
We want to cycle through the preceding days until we reach the maximum day count passed into this function.
193 date = self
194 for i in ( 1..maximum_day_count )
Go back one day.
197 date = date.prev_day
If this is a Commons adjournnment day or a Commons virtual sitting day ...
200 if date.is_commons_adjournment_day? or date.is_commons_virtual_sitting_day?
... add one to the non-sitting scrutiny day count.
203 non_sitting_scrutiny_day_count +=1
If this is not a Commons adjournnment day or a Commons virtual sitting day ...
206 else
... stop cycling through preceding days.
209 break
210 end
211 end
If the total number of continuous non-sitting scrutiny days is more than the maximum day count ...
214 if non_sitting_scrutiny_day_count > maximum_day_count
... then this day does not count as a non-sitting scrutiny day.
217 is_commons_non_sitting_scrutiny_day = false
If the total number of continuous non-sitting scrutiny days is less than or the same as the maximum day count ...
220 else
... then this day does count as a non-sitting scrutiny day.
223 is_commons_non_sitting_scrutiny_day = true
224 end
Returns if this day is a Commons non-sitting scrutiny day
227 is_commons_non_sitting_scrutiny_day
228 end
229 end
During a short adjournment, adjournment days count toward the scrutiny period.
This method allows the definition of a “short” adjournment to be adjusted by passing in a maximum day count.
In all known cases “short” is defined as not more than four days.
For the purposes of calculating non-sitting scrutiny days, virtual sitting days also count.
241 def is_lords_non_sitting_scrutiny_day?( maximum_day_count )
245 if self.is_lords_adjournment_day? or self.is_lords_virtual_sitting_day?
Having found that this is a Lords adjournnment day or a Lords virtual sitting day, we start the adjournment day count at 1.
249 non_sitting_scrutiny_day_count = 1
We want to cycle through the following days until we reach the maximum day count passed into this function.
253 date = self
254 for i in ( 1..maximum_day_count )
Go forward one day.
258 date = date.next_day
If this is a Lords adjournnment day or a Lords virtual sitting day ...
261 if date.is_lords_adjournment_day? or date.is_lords_virtual_sitting_day?
... add one to the non-sitting scrutiny day count.
264 non_sitting_scrutiny_day_count +=1
If this is not a Lords adjournnment day or a Lords virtual sitting day ...
267 else
... stop cycling through following days.
270 break
271 end
272 end
We want to cycle through the preceding days until we reach the maximum day count passed into this function.
275 date = self
276 for i in ( 1..maximum_day_count )
Go back one day.
279 date = date.prev_day
If this is a Lords adjournnment day or a Lords virtual sitting day ...
282 if date.is_lords_adjournment_day? or date.is_lords_virtual_sitting_day?
... add one to the non-sitting scrutiny day count.
285 non_sitting_scrutiny_day_count +=1
If this is not a Lords adjournnment day or a Lords virtual sitting day ...
288 else
... stop cycling through preceding days.
291 break
292 end
293 end
If the total number of continuous non-sitting scrutiny days is more than the maximum day count ...
296 if non_sitting_scrutiny_day_count > maximum_day_count
... then this day does not count as a non-sitting scrutiny day.
299 is_lords_non_sitting_scrutiny_day = false
If the total number of continuous non-sitting scrutiny days is less than or the same as the maximum day count ...
302 else
... then this day does count as a non-sitting scrutiny day.
305 is_lords_non_sitting_scrutiny_day = true
306 end
Returns if this day is a Lords non-sitting scrutiny day
309 is_lords_non_sitting_scrutiny_day
310 end
311 end
(End of methods to calculate non-sitting scrutiny days in both Houses.)
A scrutiny day in the Commons is either an actual sitting day in the Commons, or a non-sitting scrutiny day in the Commons.
We pass '4' as the maximum day count to the non-sitting scrutiny day calculation, because non-sitting scrutiny days are days within a series of not more than four non-sitting days.
321 def is_commons_scrutiny_day?
322 self.is_commons_actual_sitting_day? or self.is_commons_non_sitting_scrutiny_day?( 4 )
323 end
A scrutiny day in the Lords is either an actual sitting day in the Lords, or a non-sitting scrutiny day in the Lords.
We pass '4' as the maximum day count to the non-sitting scrutiny day calculation, because non-sitting scrutiny days are days within a series of not more than four non-sitting days.
331 def is_lords_scrutiny_day?
332 self.is_lords_actual_sitting_day? or self.is_lords_non_sitting_scrutiny_day?( 4 )
333 end
337 def is_either_house_scrutiny_day?
338 self.is_commons_scrutiny_day? or self.is_lords_scrutiny_day?
339 end
343 def is_joint_scrutiny_day?
344 self.is_commons_scrutiny_day? and self.is_lords_scrutiny_day?
345 end
(End of set of methods to work out the type of a given day.)
This method is used when a Statutory Instrument is laid outside of a scrutiny period, that is: during a non-sitting period of more than four days, or during a period in which Parliament is prorogued. In such cases, the clock starts from the first actual sitting day in either House following the laying.
This method is used for bicameral negative SIs - and bicameral made affirmatives where the enabling legislation specifies that either House can be sitting.
358 def first_scrutiny_day_in_either_house
If this is a day on which the calendar is not yet populated ...
361 if self.is_calendar_not_populated?
... then we cannot find a first scrutiny day so we stop looking.
364 return nil
If this is a day on which the calendar is populated ...
367 else
... then if this is not a scrutiny day in either House ...
370 unless self.is_either_house_scrutiny_day?
... then go to the next day and check that.
373 self.next_day.first_scrutiny_day_in_either_house
... then if this is a scrutiny day in either House ...
376 else
... then return this day as the first scrutiny day in either House.
379 self
380 end
381 end
382 end
This method is used when a Statutory Instrument is laid outside of a scrutiny period, that is: during an adjournment of more than four days, or during a period in which Parliament is prorogued. The clock starts from the first actual sitting day in both Houses following the laying.
This method is used for bicameral made affirmatives where the enabling legislation specifies that both Houses must be sitting.
390 def first_joint_scrutiny_day
If this is a day on which the calendar is not yet populated ...
393 if self.is_calendar_not_populated?
... then we cannot find a first scrutiny day so we stop looking.
396 return nil
If this is a day on which the calendar is populated ...
399 else
... then if this is not a scrutiny day in both Houses ...
402 unless self.is_joint_scrutiny_day?
... then go to the next day and check that.
405 self.next_day.first_joint_scrutiny_day
... then if this is a scrutiny day in both Houses ...
408 else
... then return this day as the first scrutiny day in both Houses.
411 self
412 end
413 end
414 end
This method is used when a Statutory Instrument is laid outside of a scrutiny period, that is: during an adjournment of more than four days, or during a period in which Parliament is prorogued. The clock starts from the first actual sitting day in the Commons following the laying.
This method is used for negative or made affirmative SIs - laid in the Commons and not laid in the Lords.
422 def first_commons_scrutiny_day
If this is a day on which the calendar is not yet populated ...
425 if self.is_calendar_not_populated?
... then we cannot find a first Commons scrutiny day so we stop looking.
428 return nil
If this is a day on which the calendar is populated ...
431 else
... then if this is not a scrutiny day in the Commons ...
434 unless self.is_commons_scrutiny_day?
... then go to the next day and check that.
437 self.next_day.first_commons_scrutiny_day
... then if this is a scrutiny day in the Commons ...
440 else
... then return this day as the first scrutiny day in the Commons.
443 self
444 end
445 end
446 end
This method is used when a Proposed Negative Statutory Instrument is laid.
Even if a PNSI is laid on a joint parliamentary sitting day, the clock does not start until the next joint parliamentary sitting day.
454 def first_joint_parliamentary_sitting_day
If this is a day on which the calendar is not yet populated ...
457 if self.is_calendar_not_populated?
... then we cannot find a first parliamentary sitting day in both Houses so we stop looking.
460 return nil
If this is a day on which the calendar is populated ...
463 else
... then if this is not a parliamentary sitting day in both Houses ...
466 unless self.is_joint_parliamentary_sitting_day?
... then go to the next day and check that.
469 self.next_day.first_joint_parliamentary_sitting_day
... then if this is a parliamentary sitting day in both Houses ...
472 else
... then return this day as the first parliamentary sitting day in both Houses.
475 self
476 end
477 end
478 end
This method is used to calculate periods A and B for treaties.
Even if a treaty is laid or a ministerial statement is made on a joint actual sitting day, the clock does not start until the next joint actual sitting day.
486 def first_joint_actual_sitting_day
If this is a day on which the calendar is not yet populated ...
489 if self.is_calendar_not_populated?
... then we cannot find a first actual sitting day in both Houses so we stop looking.
492 return nil
If this is a day on which the calendar is populated ...
495 else
... then if this is not an actual sitting day in both Houses ...
498 unless self.is_joint_actual_sitting_day?
... then go to the next day and check that.
501 self.next_day.first_joint_actual_sitting_day
... then if this is an actual sitting day in both Houses ...
504 else
... then return this day as the first actual sitting day in both Houses.
507 self
508 end
509 end
510 end
This method is used by the House of Commons only sitting day calculation.
Even if an instrument is laid on a House of Commons actual sitting day, the clock does not start until the next House of Commons actual sitting day.
518 def first_commons_actual_sitting_day
If this is a day on which the calendar is not yet populated ...
521 if self.is_calendar_not_populated?
... then we cannot find a first actual sitting day in the House of Commons so we stop looking.
524 return nil
If this is a day on which the calendar is populated ...
527 else
... then if this is not an actual sitting day in the House of Commons ...
530 unless self.is_commons_actual_sitting_day?
... then go to the next day and check that.
533 self.next_day.first_commons_actual_sitting_day
... then if this is an actual sitting day in the House of Commons ...
536 else
... then return this day as the first actual sitting day in the House of Commons.
539 self
540 end
541 end
542 end
(End of set of methods to find the first day of a given type.)
A calendar day may sit in either a dissolution period or a Parliament period.
If a calendar day sits inside a Parliament period, it may sit inside either a session or a prorogation period.
556 def dissolution_period
557 DissolutionPeriod.all.where( "start_date <= ?", self ).where( "end_date >= ?", self).first
558 end
561 def parliament_period
562 ParliamentPeriod.find_by_sql(
563 "
564 SELECT *
565 FROM parliament_periods
566 WHERE start_date <= '#{self}'
567 AND (
568 end_date >= '#{self}'
569 OR
570 end_date IS NULL
571 )
572 "
573 ).first
574 end
577 def prorogation_period
578 ProrogationPeriod.all.where( "start_date <= ?", self ).where( "end_date >= ?", self).first
579 end
582 def session
583 Session.find_by_sql(
584 "
585 SELECT *
586 FROM sessions
587 WHERE start_date <= '#{self}'
588 AND (
589 end_date >= '#{self}'
590 OR
591 end_date IS NULL
592 )
593 "
594 ).first
595 end
598 def is_final_day_of_session?
599 is_final_day_of_session = false
600 session = Session.all.where( "end_date = ?", self )
601 is_final_day_of_session = true unless session.empty?
602 is_final_day_of_session
603 end
607 def preceding_session
608 Session.all.where( "start_date < ?", self ).order( "start_date DESC" ).first
609 end
This method is used to determine which session papers laid in prorogation are recorded in.
613 def following_session
614 Session.all.where( "start_date > ?", self ).order( "start_date" ).first
615 end
618 def commons_day_type
619 if self.is_commons_parliamentary_sitting_day?
620 day_type = 'Parliamentary sitting day'
621 elsif self.is_commons_actual_sitting_day?
622 day_type = "Continuation sitting day"
623 elsif self.is_commons_virtual_sitting_day?
624 day_type = 'Virtual sitting day'
625 elsif self.is_commons_non_sitting_scrutiny_day?( 4 )
626 day_type = 'Scrutiny non-sitting day'
627 elsif self.is_commons_adjournment_day?
628 day_type = self.commons_adjournment_day_label
629 elsif self.session
630 day_type = 'Session day of unknown type'
631 elsif self.is_prorogation_day?
632 day_type = 'Prorogation'
633 elsif self.is_dissolution_day?
634 day_type = 'Dissolution'
635 end
636 day_type
637 end
640 def lords_day_type
641 if self.is_lords_parliamentary_sitting_day?
642 day_type = 'Parliamentary sitting day'
643 elsif self.is_lords_actual_sitting_day?
644 day_type = "Continuation sitting day"
645 elsif self.is_lords_virtual_sitting_day?
646 day_type = 'Virtual sitting day'
647 elsif self.is_lords_non_sitting_scrutiny_day?( 4 )
648 day_type = 'Scrutiny non-sitting day'
649 elsif self.is_lords_adjournment_day?
650 day_type = self.lords_adjournment_day_label
651 elsif self.session
652 day_type = 'Session day of unknown type'
653 elsif self.is_prorogation_day?
654 day_type = 'Prorogation'
655 elsif self.is_dissolution_day?
656 day_type = 'Dissolution'
657 end
658 day_type
659 end
662 def is_commons_scrutiny_day_label
663 if self.is_commons_scrutiny_day?
664 label = 'True'
665 else
666 label = 'False'
667 end
668 label
669 end
672 def is_lords_scrutiny_day_label
673 if self.is_lords_scrutiny_day?
674 label = 'True'
675 else
676 label = 'False'
677 end
678 label
679 end
682 def commons_adjournment_day_label
683 commons_adjournment_day_label = 'Adjournment day'
We attempt to find a recess on this date, in this House.
686 recess_date = RecessDate
687 .all
688 .where( "start_date <= ?", self )
689 .where( "end_date >= ?", self )
690 .where( house_id: 1 )
691 .first
If we find a recess date on this day, in this House ...
694 if recess_date
... we append the description of the recess date to the label
697 commons_adjournment_day_label += ' (' + recess_date.description + ')'
698 end
699 commons_adjournment_day_label
700 end
703 def lords_adjournment_day_label
704 lords_adjournment_day_label = 'Adjournment day'
We attempt to find a recess on this date, in this House.
707 recess_date = RecessDate
708 .all
709 .where( "start_date <= ?", self )
710 .where( "end_date >= ?", self )
711 .where( house_id: 2 )
712 .first
If we find a recess date on this day, in this House ...
715 if recess_date
... we append the description of the recess date to the label
718 lords_adjournment_day_label += ' (' + recess_date.description + ')'
719 end
720 lords_adjournment_day_label
721 end
722 end