class date has function this(year, month, day) do this.@set(year, month, day) end function @set(year, month, day) do if month > 12 do year += (month - 1) / 12 month = (month - 1) % 12 + 1 end while day > (ndays = this.@ndaysofmonth(year, month)) do day -= ndays; month += 1 if month > 12 do month -= 12; year += 1 end end while day < 1 do month += 1 if month < 1 do month += 12; year -= 1 end day += this.@ndaysofmonth(year, month) end this.@year, this.@month, this.@day = year, month, day end function @ndaysofmonth(year, month) do if month == 2 then if year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) then 29 # leap year else 28 # non-leap year end elif month in [4, 6, 9, 11] then 30 else 31 end end function .year do this.@year end function .month do this.@month end function .day do this.@day end function operator +=(rhs) do this.@set(this.@year, this.@month, this.@day + rhs) return this end function operator -=(rhs) do this.@set(this.@year, this.@month, this.@day - rhs) return this end function operator +(rhs) do tmp = this.clone() return (tmp += rhs) end function operator -(rhs) do tmp = this.clone() return (tmp -= rhs) end function tostring do "%04d-%02d-%02d" % [this.@year, this.@month, this.@day] end end