{curl 8.0 applet}
{curl-file-attributes character-encoding = "utf8"}
{applet manifest = "manifest.mcurl",
	{compiler-directives careful? = true}
}



{let constant package SHUKUJITSU-HOU:DateTime = {DateTime "1948-07-20", zone = DateTimeZone.utc}}
{let constant package FURIKAE-HOU   :DateTime = {DateTime "1973-07-12", zone = DateTimeZone.utc}}

{define-proc public {calculate-holiday cc:CalendarControl, date:DateTime}:(#Graphic, bool)

    let info:DateTimeInfo = date.info

    let month:int = info.month
    let day:int   = info.day
    let day-of-week:int = info.day-of-week

    let sunday?:bool = day-of-week == 7

    let holiday?:bool = {calculate-japanese-holiday date}

    {if not holiday?
     then
        set holiday? =
            {calc-private-holiday month,day}
    }

    let saturday?:bool = day-of-week == 6


    {return
        {if sunday? or holiday?
         then
            {text color = "red",background = "#ffcccc",{value day}}
         elseif saturday?
         then
            {text color = "blue",background = "#ccccff",{value day}}
         else
            null
        },
        true
    }
}

{define-proc {calc-private-holiday month:int,day:int}:bool
    {return
        {switch month
         case 12 do
            (day == 29) or (day == 30) or (day == 31)
         case 1 do
            (day == 2) or (day == 3) or (day == 4)
         else
            false
        }
    }
}

{define-proc public {calculate-japanese-holiday
                        date:DateTime
                    }:bool

    let year:int = date.info.year
    let month:int = date.info.month
    let day:int = date.info.day
    let day-of-week:int = date.info.day-of-week

    {if {SHUKUJITSU-HOU.compare date} > 0
     then
        {return false}
    }

    let result?:bool = false

    {switch month
     case 1 do
        {if day == 1
         then
            set result? = true||元日
         else
            {if (year >= 2000)
             then
                set result? = (day div 7 == 1) and (day-of-week == 1)
             elseif day == 15
             then
                set result? = true
            }
        }
     case 2 do
        {if (day == 11)
         then
            set result? = (year >= 1967)
         elseif (year == 1989) and (day == 24)
         then
            set result? = true
        }
     case 3 do
        set result? = day == {calc-shunbun-day year}
     case 4 do
        {if day == 29
         then
            set result? = true
         elseif (year == 1959) and (day == 10)
         then
            set result? = true
        }
     case 5 do
        {if (day == 3)
         then
            set result? = true
         elseif (day == 4) and (year >= 1986)
         then
            set result? = true
         elseif (day == 5)
         then
            set result? = true
         elseif (day == 6)
         then
            {if((year >= 2007) and ((day-of-week == 2) or (day-of-week == 3)))
             then
                set result? = true
            }
        }
     case 6 do
        {if ((year == 1993) and (day == 9))
         then
            set result? = true
        }
     case 7 do
        {if (year >= 2003)
         then
            set result? = ((day - 1) div 7 == 2) and (day-of-week == 1)
         elseif (year >= 1996)
         then
            set result? = day == 20
        }
     case 8 do
     case 9 do
        {if (day == {calc-shubun-day year})
         then
            set result? = true
         else
            {if (year >= 2003)
             then
                {if ((day - 1) div 7 == 2) and (day-of-week == 1)
                 then
                    set result? = true
                 elseif (day-of-week == 2)
                 then
                    set result? = day == ({calc-shubun-day year} - 1)
                }
             elseif (year >= 1966)
             then
                set result? = true
            }
        }
     case 10 do
        {if (year >= 2000)
         then
            set result? = ((day - 1) div 7 == 1) and (day-of-week == 1)
         elseif (year >= 1966)
         then
            set result? = day == 10
        }
     case 11 do
        {if (day == 3)
         then
            set result? = true
         elseif (day == 23)
         then
            set result? = true
         elseif ((year == 1990) and (day == 12))
         then
            set result? = true
        }
     case 12 do
        set result? = (day == 23) and (year >= 1989)
    }

    {if (not result?) and (day-of-week == 1)
     then

        {if {FURIKAE-HOU.compare date} > 0
         then
            set result? = {calculate-japanese-holiday date - 1day}
        }
    }

    {return result?}
}

{define-proc package {calc-shunbun-day year:int}:int
    let day:int = -1
    {if year <= 1947
     then
     elseif year <= 1979
     then
        set day = (20.8357 + (0.242194 * (year - 1980)) - ((year - 1983) / 4) asa int) asa int
     elseif year <= 2099
     then
        set day = (20.8431 + (0.242194 * (year - 1980)) - ((year - 1980) / 4) asa int) asa int
     elseif year <= 2150
     then
        set day = (21.851 + (0.242194 * (year - 1980)) - ((year - 1980) / 4) asa int) asa int
    }

    {return day}
}

{define-proc package {calc-shubun-day year:int}:int
    let day:int = -1
    {if year <= 1947
     then
     elseif year <= 1979
     then
        set day = (23.2588 + (0.242194 * (year - 1980)) - ((year - 1983) / 4) asa int) asa int
     elseif year <= 2099
     then
        set day = (23.2488 + (0.242194 * (year - 1980)) - ((year - 1980) / 4) asa int) asa int
     elseif year <= 2150
     then
        set day = (24.2488 + (0.242194 * (year - 1980)) - ((year - 1980) / 4) asa int) asa int
    }

    {return day}
}

{CalendarControl
    day-proc = calculate-holiday
}
