Easy Date Converter Advanced Version Subroutines This page explains how to write and call subroutines defined in terms of EDC statements.
A subroutine definition is any set of contiguous program statements (one per line as usual, possibly with intervening blank lines) which begins with a statement of the form:
sub {subroutine name}([{arg1}[, {arg2}[, ...]]]) and ends with endsub. For example:
call ShowDate(today) sub ShowDate(d) if d = today then output: Today's date is:; else output: The date is:; endif output: DateVal(d,CE) endsubExit from a subroutine before the end is done via return: (with no return value, since subroutines do not return anything).
Properties of subroutines:
- Subroutine definitions may be placed anywhere within a program.
- Subroutines can have from zero to four arguments. (If zero then the parentheses are still required.)
- Variables in the argument list can have any names, including names of variables used outside of the function.
- A subroutine can call other subroutines and functions.
There are some restrictions on the use of subroutines:
- An argument in a function call must be a number, a variable, today or result; it cannot be a call to afunction.
- A subroutine may not reference variables outside itself.
Now follow some sample programs illustrating the use of subroutines.
Here is an example of a subroutine which calls a defined function.
Input file Result in output window
// Example E1 date = today do 60 call subr(date) date += 1 enddo sub subr(d) tv = DaySameAsMonth(d) if tv = 1 output: DateVal(d,CE) endif endsub function DaySameAsMonth(d) if DayOf(d,CE) = MonthOf(d,CE) return: 1 else return: 0 endif endfunction
2007-04-04 CE 2007-05-05 CENote that built-in functions can be used in IF statements but not defined functions, so if DayOf(d,CE) = MonthOf(d,CE) is valid but if DaySameAsMonth(d) = 1 is not.
This example shows how an EDC program can be used in calendrical studies.
In March 2007 the U.S. introduced new rules for the start and end of Daylight Savings Time, as follows: DST begins on the 2nd Sunday in March and ends on the 1st Sunday in November. (Formerly DST began in the U.S. on the 1st Sunday of April and ended on the last Sunday of October.)
The question was raised on the CALNDR-L discussion group as to when, under the new rules, DST started and ended in the ISO Week Calendar. On 2007-03-08 Robert van Gent gave this answer:
U.S. Daylight Saving Time will always start on Sunday ISO week 10 and end on Sunday ISO week 44, except in leap years (such as 2032 and 2060) when 29 February is a Sunday when the begin and end will be in ISO weeks 11 and 45.Given below is an EDC program which solves the following problem: If DST starts on the n1th Sunday in month m1 and ends on the n2th Sunday in month m2, what are the ISO Week dates of the start and end of DST over a given range of years? (Where a zero value for n1 and n2 means 'last'.)
In this program the values of n1, m1, etc. are set appropriately for the new DST rules, and w1 and w2 are set according to Robert van Gent's statement, which, by computation, is found to be confirmed. This program uses the same defined functions NumDaysInMonthCE(m,y) and DateOfNthSundayInMonthCE(n,m,y) which were used in Example D4.
Input file Result in output window
// Example E2 n1 = 2 m1 = 3 w1 = 10 n2 = 1 m2 = 11 w2 = 44 output: The hypothesis to be tested is that output: if DST begins on Sunday #;; output: val(n1); output: in month #;; output: val(m1) output: and ends on Sunday #;; output: val(n2); output: in month #;; output: val(m2) output: then in almost all years DST will output: begin on the Sunday of ISO week #;; output: val(w1); output: and output: end on the Sunday of ISO week #;; output: val(w2);; output: . bl start_year = 2007 end_year = 2100 output: For the period of years; output: val(start_year); output: through; output: val(end_year) output: this proposition is *not* true as follows: bl year = start_year count = 0 do tv = ShowSundayIfNotISOWeek(n1,m1,w1,year) if tv = 1 then count += 1 endif tv = ShowSundayIfNotISOWeek(n2,m2,w2,year) if tv = 1 then count += 1 bl endif year += 1 if year > end_year then exitdo endif enddo if count = 0 then output: So there are no exceptions to this output: proposition in this period of years. endif function ShowSundayIfNotISOWeek(n,m,w,y) date = DateOfNthSundayInMonthCE(n,m,y) ifnot WeekOf(date,ISO) = w then call DisplayLine(date,n,m) return: 1 else return: 0 endif endfunction sub DisplayLine(date,n,m) output: DoW(date); output: #;; output: val(n); output: in; output: MonthName(m,CE); output: YearOf(date, CE); output: is; output: dateval(date,CE); output: =; output: dateval(date,ISO);; output: . endsub function NumDaysInMonthCE(m,y) date1 = Date(CE,y,m,1) if m < 12 then m += 1 date2 = Date(CE,y,m,1) else y += 1 date2 = Date(CE,y,1,1) endif return: Subtract(date1,date2) endfunction function DateOfNthSundayInMonthCE(n,m,y) num_days_in_month = NumDaysInMonthCE(m,y) if n >= 1 then k = 0 date1 = Date(CE,y,m,1) do if DoW(date1) = Sunday then k += 1 if k = n then return: date1 endif endif if DayOf(date1,CE) = num_days_in_month then return: 0 // n too large. endif date1 += 1 enddo elseif n = 0 then // Seeking last Sunday in the month. date1 = Date(CE,y,m,num_days_in_month) do if DoW(date1) = Sunday then return: date1 endif date1 -= 1 enddo else return: 0 // n < 0 endif return: date1 endfunction
The hypothesis to be tested is that if DST begins on Sunday #2 in month #3 and ends on Sunday #1 in month #11 then in almost all years DST will begin on the Sunday of ISO week #10 and end on the Sunday of ISO week #44. For the period of years 2007 through 2100 this proposition is *not* true as follows: Sunday #2 in March 2032 is 2032-03-14 CE = 2032-W11-7 ISO. Sunday #1 in November 2032 is 2032-11-07 CE = 2032-W45-7 ISO. Sunday #2 in March 2060 is 2060-03-14 CE = 2060-W11-7 ISO. Sunday #1 in November 2060 is 2060-11-07 CE = 2060-W45-7 ISO. Sunday #2 in March 2088 is 2088-03-14 CE = 2088-W11-7 ISO. Sunday #1 in November 2088 is 2088-11-07 CE = 2088-W45-7 ISO.By changing the values assigned to n1, m1, etc., this program may be used to show the following:
1. Under the old rules, and the rules still used by almost all other countries in the world, DST almost always ends with the Sunday of Week 43 in the ISO Week Calendar, but it begins about half the time on the Sunday of ISO Week 13 and the rest of the time with the Sunday of ISO Week 14.
2. If DST begins on the last Sunday in March then there is also an even division of ISO Week beginnings (Weeks 12 and 13), but if it begins on the 1st, 2nd, 3rd or 4th Sunday in March then it always begins on the same ISO Sunday (in Week 9, 10, 11 or 12 respectively) with exceptions in years 2032, 2060 and 2088 (in the period 2007-2100).
After seeing the example above Karl Palmen asked:
Can it [EDC] show that European DST begins on Sunday ISO week 14, if there are five Sundays in either February or March, else Sunday ISO week 13.The following program tests this hypothesis, which is found to be true for the years 1800 through 2201. Since the structure of the Common Era Calendar and the ISO Week Calendar (which is defined in terms of the former) repeats every 400 years, the hypothesis is true for all years.
This program uses the two defined functions in the previous example, and uses a new defined function, NumSundaysInMonthCE(). The program outputs a '.' for each year when there is no exception to the hypothesis; most of these have been omitted from the output given below.
Input file Result in output window
// Example E3 output: The hypothesis to be tested is that if there output: are five Sundays in either February or March output: then European DST begins on Sunday ISO week 14 output: else it begins on Sunday ISO week 13. bl start_year = 1800 end_year = 2201 output: For the period of years; output: val(start_year); output: through; output: val(end_year) output: this hypothesis is *not* true as follows: bl year = start_year do date = DateOfNthSundayInMonthCE(1,4,year) // Date on which European DST begins. iso_week = WeekOf(date,ISO) // ISO week number. num_sun_feb = NumSundaysInMonthCE(2,year) num_sun_mar = NumSundaysInMonthCE(3,year) exception = 0 if num_sun_feb = 5 then ifnot iso_week = 14 then exception = 1 endif elseif num_sun_mar = 5 then ifnot iso_week = 14 then exception = 1 endif elseifnot iso_week = 13 then exception = 1 endif if exception = 1 then output: The hypothesis is not true of year; output: val(year);; output: . stop else output: .; endif year += 1 if year > end_year then exitdo endif enddo bl bl output: So there are no exceptions to this output: hypothesis in this period of years. function NumSundaysInMonthCE(m,y) date = DateOfNthSundayInMonthCE(1,m,y) // This is the date of the 1st Sunday. num_sundays = 1 do date = Add(7,date) if m = 12 then if MonthOf(date,CE) = 1 then exitdo endif elseif MonthOf(date,CE) > m then exitdo else num_sundays += 1 endif enddo return: num_sundays endfunction function NumDaysInMonthCE(m,y) date1 = Date(CE,y,m,1) if m < 12 then m += 1 date2 = Date(CE,y,m,1) else y += 1 date2 = Date(CE,y,1,1) endif return: Subtract(date1,date2) endfunction function DateOfNthSundayInMonthCE(n,m,y) num_days_in_month = NumDaysInMonthCE(m,y) if n >= 1 then k = 0 date1 = Date(CE,y,m,1) do if DoW(date1) = Sunday then k += 1 if k = n then return: date1 endif endif if DayOf(date1,CE) = num_days_in_month then return: 0 // n too large. endif date1 += 1 enddo elseif n = 0 then // Seeking last Sunday in the month. date1 = Date(CE,y,m,num_days_in_month) do if DoW(date1) = Sunday then return: date1 endif date1 -= 1 enddo else return: 0 // n < 0 endif return: date1 endfunction
The hypothesis to be tested is that if there are five Sundays in either February or March then European DST begins on Sunday ISO week 14 else it begins on Sunday ISO week 13. For the period of years 1800 through 2201 this hypothesis is *not* true as follows: . . . . . [snip] So there are no exceptions to this hypothesis in this period of years.
Easy Date Converter Advanced Version Main Page Date/Calendar Software Hermetic Systems Home Page