Discordian date
You are encouraged to solve this task according to the task description, using any language you may know.
Convert a given date from the Gregorian calendar to the Discordian calendar.
See Also
Ada
discordian.adb: <lang Ada>with Ada.Calendar.Arithmetic; with Ada.Text_IO; procedure Discordian is
use Ada.Calendar; subtype Year_Number is Integer range 3067 .. 3565; type Seasons is (Chaos, Discord, Confusion, Bureaucracy, The_Aftermath); subtype Day_Number is Integer range 1 .. 73;
type Discordian_Date is record Year : Year_Number; Season : Seasons; Day : Day_Number; Is_Tibs_Day : Boolean := False; end record;
procedure Convert (From : Time; To : out Discordian_Date) is use Ada.Calendar.Arithmetic; First_Day : Time; Number_Days : Day_Count; begin First_Day := Time_Of (Year => Year (From), Month => 1, Day => 1); Number_Days := From - First_Day;
To.Year := Year (Date => From) + 1166; To.Is_Tibs_Day := False; if (To.Year - 2) mod 4 = 0 then if Number_Days > 59 then Number_Days := Number_Days - 1; elsif Number_Days = 59 then To.Is_Tibs_Day := True; end if; end if; To.Day := Day_Number (Number_Days mod 73 + 1); case Number_Days / 73 is when 0 => To.Season := Chaos; when 1 => To.Season := Discord; when 2 => To.Season := Confusion; when 3 => To.Season := Bureaucracy; when 4 => To.Season := The_Aftermath; when others => raise Constraint_Error; end case; end Convert;
procedure Put (Item : Discordian_Date) is begin Ada.Text_IO.Put ("YOLD" & Integer'Image (Item.Year)); if Item.Is_Tibs_Day then Ada.Text_IO.Put (", St. Tib's Day"); else Ada.Text_IO.Put (", " & Seasons'Image (Item.Season)); Ada.Text_IO.Put (" " & Integer'Image (Item.Day)); end if; Ada.Text_IO.New_Line; end Put;
Test_Day : Time; Test_DDay : Discordian_Date;
begin
Test_Day := Clock; Convert (From => Test_Day, To => Test_DDay); Put (Test_DDay); Test_Day := Time_Of (Year => 2012, Month => 2, Day => 28); Convert (From => Test_Day, To => Test_DDay); Put (Test_DDay); Test_Day := Time_Of (Year => 2012, Month => 2, Day => 29); Convert (From => Test_Day, To => Test_DDay); Put (Test_DDay); Test_Day := Time_Of (Year => 2012, Month => 3, Day => 1); Convert (From => Test_Day, To => Test_DDay); Put (Test_DDay); Test_Day := Time_Of (Year => 2010, Month => 7, Day => 22); Convert (From => Test_Day, To => Test_DDay); Put (Test_DDay); Test_Day := Time_Of (Year => 2012, Month => 9, Day => 2); Convert (From => Test_Day, To => Test_DDay); Put (Test_DDay); Test_Day := Time_Of (Year => 2012, Month => 12, Day => 31); Convert (From => Test_Day, To => Test_DDay); Put (Test_DDay);
end Discordian;</lang>
Output:
YOLD 3177, CHAOS 21 YOLD 3178, CHAOS 59 YOLD 3178, St. Tib's Day YOLD 3178, CHAOS 60 YOLD 3176, CONFUSION 56 YOLD 3178, BUREAUCRACY 25 YOLD 3178, THE_AFTERMATH 73
AWK
<lang AWK>
- DDATE.AWK - Gregorian to Discordian date contributed by Dan Nielsen
- syntax: GAWK -f DDATE.AWK [YYYYMMDD | YYYY-MM-DD | MM-DD-YYYY | DDMMMYYYY | YYYY] ...
- examples:
- GAWK -f DDATE.AWK today
- GAWK -f DDATE.AWK 20110722 one date
- GAWK -f DDATE.AWK 20110722 20120229 two dates
- GAWK -f DDATE.AWK 2012 yearly calendar
BEGIN {
split("Chaos,Discord,Confusion,Bureaucracy,The Aftermath",season_arr,",") split("Sweetmorn,Boomtime,Pungenday,Prickle-Prickle,Setting Orange",weekday_arr,",") split("Mungday,Mojoday,Syaday,Zaraday,Maladay",apostle_holyday_arr,",") split("Chaoflux,Discoflux,Confuflux,Bureflux,Afflux",season_holyday_arr,",") split("31,28,31,30,31,30,31,31,30,31,30,31",days_in_month,",") # days per month in non leap year split("0 31 59 90 120 151 181 212 243 273 304 334",rdt," ") # relative day table mmm = "JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC"
- 1 2 3 4 5 6 7 8 9 10 11 12
if (ARGV[1] == "") { # use current date ARGV[ARGC++] = strftime("%Y%m%d") # GAWK only # ARGV[ARGC++] = dos_date() # any AWK # timetab(arr); ARGV[ARGC++] = sprintf("%04d%02d%02d",arr["YEAR"],arr["MONTH"],arr["DAY"]) # TAWK only } for (argno=1; argno<=ARGC-1; argno++) { # validate command line arguments print("") x = toupper(ARGV[argno]) if (x ~ /^[0-9][0-9][0-9][0-9][01][0-9][0-3][0-9]$/) { # YYYYMMDD main(x) } else if (x ~ /^[0-9][0-9][0-9][0-9]-[01][0-9]-[0-3][0-9]$/) { # YYYY-MM-DD gsub(/-/,"",x) main(x) } else if (x ~ /^[01][0-9]-[0-3][0-9]-[0-9][0-9][0-9][0-9]$/) { # MM-DD-YYYY main(substr(x,7,4) substr(x,1,2) substr(x,4,2)) } else if (x ~ /^[0-3][0-9](JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)[0-9][0-9][0-9][0-9]$/) { # DDMMMYYYY main(sprintf("%04d%02d%02d",substr(x,6,4),int((match(mmm,substr(x,3,3))/4)+1),substr(x,1,2))) } else if (x ~ /^[0-9][0-9][0-9][0-9]$/) { # YYYY yearly_calendar(x) } else { error("begin") } } if (errors == 0) { exit(0) } else { exit(1) }
} function main(x, d,dyear,m,season_day,season_nbr,text,weekday_nbr,y,year_day) {
y = substr(x,1,4) + 0 m = substr(x,5,2) + 0 d = substr(x,7,2) + 0 days_in_month[2] = (leap_year(y) == 1) ? 29 : 28 if (m < 1 || m > 12 || d < 1 || d > days_in_month[m]+0) { error("main") return } year_day = rdt[m] + d dyear = y + 1166 # Discordian year season_nbr = int((year_day - 1 ) / 73) + 1 season_day = ((year_day - 1) % 73) + 1 weekday_nbr = ((year_day - 1 ) % 5) + 1 if (season_day == 5) { text = ", " apostle_holyday_arr[season_nbr] } else if (season_day == 50) { text = ", " season_holyday_arr[season_nbr] } if (leap_year(y) && m == 2 && d == 29) { printf("%04d-%02d-%02d is St. Tib's day, Year of Our Lady of Discord %s\n",y,m,d,dyear) } else { printf("%04d-%02d-%02d is %s, %s %s, Year of Our Lady of Discord %s%s\n", y,m,d,weekday_arr[weekday_nbr],season_arr[season_nbr],season_day,dyear,text) }
} function leap_year(y) { # leap year: 0=no, 1=yes
return (y % 400 == 0 || (y % 4 == 0 && y % 100)) ? 1 : 0
} function yearly_calendar(y, d,m) {
days_in_month[2] = (leap_year(y) == 1) ? 29 : 28 for (m=1; m<=12; m++) { for (d=1; d<=days_in_month[m]; d++) { main(sprintf("%04d%02d%02d",y,m,d)) } }
} function dos_date( cmd,x) { # under Microsoft Windows XP
cmd = "DATE <NUL" cmd | getline x # The current date is: MM/DD/YYYY close(cmd) # close pipe return sprintf("%04d%02d%02d",substr(x,28,4),substr(x,22,2),substr(x,25,2))
} function error(x) {
printf("error: argument %d is invalid, %s, in %s\n",argno,ARGV[argno],x) errors++
} </lang>
output:
GAWK -f DDATE.AWK 2011-08-22 is Prickle-Prickle, Bureaucracy 15, Year of Our Lady of Discord 3177 GAWK -f DDATE.AWK 20110722 20120229 2011-07-22 is Pungenday, Confusion 57, Year of Our Lady of Discord 3177 2012-02-29 is St. Tib's day, Year of Our Lady of Discord 3178
C
<lang C>#include <string.h>
- include <malloc.h>
- include <stdlib.h>
- include <stdio.h>
- include <time.h>
- define season( x ) ((x) == 0 ? "Chaos" :\
(x) == 1 ? "Discord" :\ (x) == 2 ? "Confusion" :\ (x) == 3 ? "Bureaucracy" :\ "The Aftermath")
- define date( x ) ((x)%73 == 0 ? 73 : (x)%73)
- define leap_year( x ) ((x) % 400 == 0 || (((x) % 4) == 0 && (x) % 100))
char * ddate( int y, int d ){
int dyear = 1166 + y; char * result = malloc( 100 * sizeof( char ) );
if( leap_year( y ) ){ if( d == 60 ){ sprintf( result, "St. Tib's Day, YOLD %d", dyear ); return result; } else if( d >= 60 ){ -- d; } }
sprintf( result, "%s %d, YOLD %d", season( d/73 ), date( d ), dyear );
return result;
}
int day_of_year( int y, int m, int d ){
int month_lengths[ 12 ] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
for( ; m > 1; m -- ){ d += month_lengths[ m - 2 ]; if( m == 3 && leap_year( y ) ){ ++ d; } } return d;
}
int main( int argc, char * argv[] ){
time_t now; struct tm * now_time; int year, doy;
if( argc == 1 ){ now = time( NULL ); now_time = localtime( &now ); year = now_time->tm_year + 1900; doy = now_time->tm_yday + 1; } else if( argc == 4 ){ year = atoi( argv[ 1 ] ); doy = day_of_year( atoi( argv[ 1 ] ), atoi( argv[ 2 ] ), atoi( argv[ 3 ] ) ); } printf( "%s\n", ddate( year, doy ) );
return 0;
}</lang>
Demonstration:
$ ./ddate #today is Jan 7th, 2011 Chaos 7, YOLD 3177 $ ./ddate 2011 1 7 Chaos 7, YOLD 3177 $ ./ddate 2012 2 28 Chaos 59, YOLD 3178 $ ./ddate 2012 2 29 St. Tib's Day, YOLD 3178 $ ./ddate 2012 3 1 Chaos 60, YOLD 3178 $ ./ddate 2010 7 22 Confusion 57, YOLD 3176
D
<lang d>import std.stdio, std.datetime, std.conv, std.string;
immutable seasons = ["Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"]; immutable weekday = ["Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange"]; immutable apostle = ["Mungday", "Mojoday", "Syaday", "Zaraday", "Maladay"]; immutable holiday = ["Chaoflux", "Discoflux", "Confuflux", "Bureflux", "Afflux"];
string discordianDate(in Date date) {
auto dyear = to!string(date.year + 1166);
auto isLeapYear = date.isLeapYear; if (isLeapYear && date.month == 2 && date.day == 29) return "St. Tib's Day, in the YOLD " ~ dyear;
auto doy = date.dayOfYear; if (isLeapYear && doy >= 60) doy--;
auto dsday = doy % 73; // season day if (dsday == 5) return apostle[doy / 73] ~ ", in the YOLD " ~ dyear; if (dsday == 50) return holiday[doy / 73] ~ ", in the YOLD " ~ dyear;
auto dseas = seasons[doy / 73]; auto dwday = weekday[(doy-1) % 5];
return format("%s, day %s of %s in the YOLD %s", dwday, dsday, dseas, dyear);
}
void main() {
auto today = cast(Date)Clock.currTime(); auto ddate = discordianDate(today); writeln(ddate);
} </lang>
<lang d>unittest {
assert(discordianDate(Date(2010,7,22)) == "Pungenday, day 57 of Confusion in the YOLD 3176"); assert(discordianDate(Date(2012,2,28)) == "Prickle-Prickle, day 59 of Chaos in the YOLD 3178"); assert(discordianDate(Date(2012,2,29)) == "St. Tib's Day, in the YOLD 3178"); assert(discordianDate(Date(2012,3, 1)) == "Setting Orange, day 60 of Chaos in the YOLD 3178"); assert(discordianDate(Date(2010,1, 5)) == "Mungday, in the YOLD 3176"); assert(discordianDate(Date(2011,5, 3)) == "Discoflux, in the YOLD 3177");
}</lang>
Euphoria
<lang euphoria>function isLeapYear(integer year)
return remainder(year,4)=0 and remainder(year,100)!=0 or remainder(year,400)=0
end function
constant YEAR = 1, MONTH = 2, DAY = 3, DAY_OF_YEAR = 8
constant month_lengths = {31,28,31,30,31,30,31,31,30,31,30,31} function dayOfYear(sequence Date)
integer d if length(Date) = DAY_OF_YEAR then d = Date[DAY_OF_YEAR] else d = Date[DAY] for i = Date[MONTH]-1 to 1 by -1 do d += month_lengths[i] if i = 2 and isLeapYear(Date[YEAR]) then d += 1 end if end for end if return d
end function
constant seasons = {"Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"} constant weekday = {"Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange"} constant apostle = {"Mungday", "Mojoday", "Syaday", "Zaraday", "Maladay"} constant holiday = {"Chaoflux", "Discoflux", "Confuflux", "Bureflux", "Afflux"}
function discordianDate(sequence Date)
sequence dyear, dseas, dwday integer leap, doy, dsday dyear = sprintf("%d",Date[YEAR]+1166) leap = isLeapYear(Date[YEAR]) if leap and Date[MONTH] = 2 and Date[DAY] = 29 then return "St. Tib's Day, in the YOLD " & dyear end if doy = dayOfYear(Date) if leap and doy >= 60 then doy -= 1 end if dsday = remainder(doy,73) if dsday = 5 then return apostle[doy/73+1] & ", in the YOLD " & dyear elsif dsday = 50 then return holiday[doy/73+1] & ", in the YOLD " & dyear end if dseas = seasons[doy/73+1] dwday = weekday[remainder(doy-1,5)+1] return sprintf("%s, day %d of %s in the YOLD %s", {dwday, dsday, dseas, dyear})
end function
sequence today today = date() today[YEAR] += 1900 puts(1, discordianDate(today))</lang>
F#
<lang F#>open System
let seasons = [| "Chaos"; "Discord"; "Confusion"; "Bureaucracy"; "The Aftermath" |]
let ddate (date:DateTime) =
let dyear = date.Year + 1166 let leapYear = DateTime.IsLeapYear(date.Year) if leapYear && date.Month = 2 && date.Day = 29 then sprintf "St. Tib's Day, %i YOLD" dyear else // compensate for St. Tib's Day let dayOfYear = if leapYear && date.DayOfYear >= 60 then date.DayOfYear - 1 else date.DayOfYear let season, dday = Math.DivRem(dayOfYear, 73) sprintf "%s %i, %i YOLD" seasons.[season] dday dyear</lang>
Go
A package modeled after the time package in the Go standard library <lang go>package ddate
import (
"strconv" "strings" "time"
)
// Predefined formats for DiscDate.Format const (
DefaultFmt = "Pungenday, Discord 5, 3131 YOLD" OldFmt = `Today is Pungenday, the 5th day of Discord in the YOLD 3131
Celebrate Mojoday` )
// Formats passed to DiscDate.Format are protypes for formated dates. // Format replaces occurrences of prototype elements (the constant strings // listed here) with values corresponding to the date being formatted. // If the date is St. Tib's Day, the string from the first date element // through the last is replaced with "St. Tib's Day". const (
protoLongSeason = "Discord" protoShortSeason = "Dsc" protoLongDay = "Pungenday" protoShortDay = "PD" protoOrdDay = "5" protoCardDay = "5th" protoHolyday = "Mojoday" protoYear = "3131"
)
var (
longDay = []string{"Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange"} shortDay = []string{"SM", "BT", "PD", "PP", "SO"} longSeason = []string{ "Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"} shortSeason = []string{"Chs", "Dsc", "Cfn", "Bcy", "Afm"} holyday = [][]string{{"Mungday", "Chaoflux"}, {"Mojoday", "Discoflux"}, {"Syaday", "Confuflux"}, {"Zaraday", "Bureflux"}, {"Maladay", "Afflux"}}
)
type DiscDate struct {
StTibs bool Dayy int // zero based day of year, meaningless if StTibs is true Year int // gregorian + 1166
}
func New(eris *time.Time) DiscDate {
t := *eris t.Month = 1 t.Day = 1 bob := int(eris.Seconds()-t.Seconds()) / (24 * 60 * 60) raw := int(eris.Year) hastur := DiscDate{Year: raw + 1166} if raw%4 == 0 && (raw%100 != 0 || raw%400 == 0) { if bob > 59 { bob-- } else if bob == 59 { hastur.StTibs = true return hastur } } hastur.Dayy = bob return hastur
}
func (dd DiscDate) Format(f string) (r string) {
var st, snarf string var dateElement bool f6 := func(proto, wibble string) { if !dateElement { snarf = r dateElement = true } if st > "" { r = "" } else { r += wibble } f = f[len(proto):] } f4 := func(proto, wibble string) { if dd.StTibs { st = "St. Tib's Day" } f6(proto, wibble) } season, day := dd.Dayy/73, dd.Dayy%73 for f > "" { switch { case strings.HasPrefix(f, protoLongDay): f4(protoLongDay, longDay[dd.Dayy%5]) case strings.HasPrefix(f, protoShortDay): f4(protoShortDay, shortDay[dd.Dayy%5]) case strings.HasPrefix(f, protoCardDay): funkychickens := "th" if day/10 != 1 { switch day % 10 { case 0: funkychickens = "st" case 1: funkychickens = "nd" case 2: funkychickens = "rd" } } f4(protoCardDay, strconv.Itoa(day+1)+funkychickens) case strings.HasPrefix(f, protoOrdDay): f4(protoOrdDay, strconv.Itoa(day+1)) case strings.HasPrefix(f, protoLongSeason): f6(protoLongSeason, longSeason[season]) case strings.HasPrefix(f, protoShortSeason): f6(protoShortSeason, shortSeason[season]) case strings.HasPrefix(f, protoHolyday): if day == 4 { r += holyday[season][0] } else if day == 49 { r += holyday[season][1] } f = f[len(protoHolyday):] case strings.HasPrefix(f, protoYear): r += strconv.Itoa(dd.Year) f = f[4:] default: r += f[:1] f = f[1:] } } if st > "" { r = snarf + st + r } return
}</lang> Example program using above package <lang go>package main
import (
"ddate" "fmt" "os" "strings" "time"
)
func main() {
pi := 1 fnord := ddate.DefaultFmt if len(os.Args) > 1 { switch os.Args[1][0] { case '+': pi++ fnord = os.Args[1][1:] case '-': usage() } } var eris *time.Time switch len(os.Args) - pi { case 0: eris = time.LocalTime() case 3: var err os.Error eris, err = time.Parse("2 1 2006", strings.Join(os.Args[pi:pi+3], " ")) if err != nil { fmt.Println(err) usage() } default: usage() } fmt.Println(ddate.New(eris).Format(fnord))
}
func usage() {
fmt.Fprintf(os.Stderr, "usage: %s [+format] [day month year]\n", os.Args[0]) os.Exit(1)
}</lang> Example output:
> ddate Pungenday, Confusion 62, 3177 YOLD > ddate 29 2 2012 St. Tib's Day, 3178 YOLD
Haskell
<lang haskell>import Data.List import Data.Time import Data.Time.Calendar.MonthDay
seasons = words "Chaos Discord Confusion Bureaucracy The_Aftermath"
discordianDate (y,m,d) = do
let doy = monthAndDayToDayOfYear (isLeapYear y) m d (season, dday) = divMod doy 73 dos = dday - fromEnum (isLeapYear y && m >2) dDate
| isLeapYear y && m==2 && d==29 = "St. Tib's Day, " ++ show (y+1166) ++ " YOLD" | otherwise = seasons!!season ++ " " ++ show dos ++ ", " ++ show (y+1166) ++ " YOLD"
putStrLn dDate</lang>
Examples:
*Main> mapM_ discordianDate [(2012,2,28),(2012,2,29),(2012,3,1),(2010,9,2),(2010,12,6)] Chaos 59, 3178 YOLD St. Tib's Day, 3178 YOLD Chaos 60, 3178 YOLD Bureaucracy 26, 3176 YOLD The_Aftermath 48, 3176 YOLD
In GHCi we can also execute shell commands.
- Using Linux utility ddate
*Main> :! ddate Today is Setting Orange, the 26th day of Bureaucracy in the YOLD 3176 *Main> :! ddate 29 2 2012 Sint Tibs *Main> :! ddate 2 9 2010 Setting Orange, Bureaucracy 26, 3176 YOLD
Icon and Unicon
This version is loosely based on a modified translation of the original ddate.c and like the original the leap year functionality is Julian not Gregorian. <lang Icon>link printf
procedure main()
Demo(2010,1,1) Demo(2010,7,22) Demo(2012,2,28) Demo(2012,2,29) Demo(2012,3,1) Demo(2010,1,5) Demo(2011,5,3) Demo(2012,2,28) Demo(2012,2,29) Demo(2012,3,1) Demo(2010,7,22) Demo(2012,12,22)
end
procedure Demo(y,m,d) #: demo display
printf("%i-%i-%i = %s\n",y,m,d,DiscordianDateString(DiscordianDate(y,m,d)))
end
record DiscordianDateRecord(year,yday,season,sday,holiday)
procedure DiscordianDate(year,month,day) #: Convert normal date to Discordian static cal initial cal := [31,28,31,30,31,30,31,31,30,31,30,31]
ddate := DiscordianDateRecord(year+1166) every (ddate.yday := day - 1) +:= cal[1 to month-1] # zero origin ddate.sday := ddate.yday if ddate.year % 4 = 2 & month = 2 & day = 29 then ddate.holiday := 1 # Note: st tibs is outside of weekdays else { ddate.season := (ddate.yday / 73) + 1 ddate.sday := (ddate.yday % 73) + 1 ddate.holiday := 1 + ddate.season * case ddate.sday of { 5 : 1; 50 : 2} } return ddate
end
procedure DiscordianDateString(ddate) #: format a Discordian Date String static days,seasons,holidays initial {
days := ["Sweetmorn","Boomtime","Pungenday","Prickle-Prickle","Setting Orange"] seasons := ["Chaos","Discord","Confusion","Bureaucracy","The Aftermath"] holidays := ["St. Tib's Day","Mungday","Chaoflux","Mojoday","Discoflux", "Syaday","Confuflux","Zaraday","Bureflux","Maladay","Afflux"] } return (( holidays[\ddate.holiday] || "," ) | ( days[1+ddate.yday%5] || ", day " || ddate.sday || " of " || seasons[ddate.season])) || " in the YOLD " || ddate.year
end</lang>
Output:
2010-1-1 = Sweetmorn, day 1 of Chaos in the YOLD 3176 2010-7-22 = Pungenday, day 57 of Confusion in the YOLD 3176 2012-2-28 = Prickle-Prickle, day 59 of Chaos in the YOLD 3178 2012-2-29 = St. Tib's Day, in the YOLD 3178 2012-3-1 = Setting Orange, day 60 of Chaos in the YOLD 3178 2010-1-5 = Mungday, in the YOLD 3176 2011-5-3 = Discoflux, in the YOLD 3177 2012-2-28 = Prickle-Prickle, day 59 of Chaos in the YOLD 3178 2012-2-29 = St. Tib's Day, in the YOLD 3178 2012-3-1 = Setting Orange, day 60 of Chaos in the YOLD 3178 2010-7-22 = Pungenday, day 57 of Confusion in the YOLD 3176 2012-12-22 = Sweetmorn, day 64 of The Aftermath in the YOLD 3178
J
<lang j>require'dates' leap=: _1j1 * 0 -/@:= 4 100 400 |/ {.@] bs=: ((#:{.) + 0 j. *@[ * {:@]) +. disc=: ((1+0 73 bs[ +^:(58<]) -/@todayno@(,: 1 1,~{.)@]) ,~1166+{.@])~ leap</lang>
Example use:
<lang> disc 2012 2 29 3178 1 59j1
disc 2012 3 1
3178 1 60j1
disc 2012 12 31
3178 5 73j1
disc 2013 1 1
3179 1 1</lang>
see talk page. But, in essence, this version uses season ordinals with a single imaginary day after the 59th of the first season, on leap years. This is implemented so that that imaginary day has been passed for all remaining days of a leap year.
JavaScript
<lang javascript>/**
* All Hail Discordia! - this script prints Discordian date using system date. * author: s1w_, lang: JavaScript */
function print_ddate(mod) {
var p; switch(mod || 0) {// <--choose display pattern or pass option by parameter default: case 0:/* Sweetmorn, Day 57 of the Season of Confusion, Anno Mung 3177 */ p="{0}, [Day {1} of the Season of {2}], Anno Mung {3}"; break; case 1:/* Sweetmorn, The 57th Day of Confusion, 3177 YOLD */ p="{0}, [The {1}th Day of {2}], {3} YOLD"; break; case 2:/* Sweetmorn, the 57th day of Confusion, AM 3177 */ p="{0}, [the {1}th day of {2}], AM {3}"; break; case 3:/* Sweetmorn / Confusion 57th / AM 3177 */ p="{0} / [{2} {1}th] / AM {3}"; break; } var ddateStr, curr, sum, extra, today, day, month, year, dSeason, dDay, season, ddate, dyear;
format = function(s, $1, $2, $3, $4) {
if ($2 != undefined) {
var postfix;
switch(parseInt($2.charAt($2.length-1))) {
case 1: postfix = '}st'; break;
case 2: postfix = '}nd'; break;
case 3: postfix = '}rd'; break;
default:postfix = '}th';
}
return p.replace(/\}th/, postfix).replace(/(\[|\])/g, ).format($1, $2, $3, $4);
}
else return p.replace(/\[.*?\]/,"{2}").format($1, $2, $3, $4);
}
String.prototype.format = function() {
var pattern = /\{\d+\}/g;
var args = arguments;
return this.replace(pattern, function(capture){ return args[capture.match(/\d+/)]; });
}
dDay = new Array("Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange"); dSeason = new Array("Chaos", "Discord", "Confusion", "Bureaucracy", "Aftermath"); curr = new Date(); extra = new Array(0,3,0,3,2,3,2,3,3,2,3,2); today = curr.getDate(); month = curr.getMonth(); year = curr.getFullYear(); sum = month * 28; for(var i=0; i<=month; i++) sum += extra[i]; sum += today; day = (sum - 1) % 5; ddate = sum % 73; season = (month==1)&&(today==29) ? "St. Tib\'s Day" : dSeason[Math.floor(sum/73)]; dyear = year+1166; ddateStr = ""+dDay[day]+ddate+season+dyear; document.write(ddateStr.replace(/(\D+)(?:(\d+)(?!St)|(?:\d+))(\D+)(\d+)/i, format));
}</lang>
Example use:
<lang javascript>print_ddate() "Sweetmorn, Day 57 of the Season of Confusion, Anno Mung 3177" print_ddate(1) "Sweetmorn, The 57th Day of Confusion, 3177 YOLD" print_ddate(2) "Sweetmorn, the 57th day of Confusion, AM 3177" print_ddate(3) "Sweetmorn / Confusion 57th / AM 3177" </lang>
look at calendar; lern about holydays
Perl 6
<lang perl6>my @seasons = < Chaos Discord Confusion Bureaucracy >, 'The Aftermath'; my @days = < Sweetmorn Boomtime Pungenday Prickle-Prickle >, 'Setting Orange'; sub ordinal ( Int $n ) { $n ~ ( $n % 100 == 11|12|13
?? 'th' !! < th st nd rd th th th th th th >[$n % 10] ) }
sub ddate ( Str $ymd ) {
my $d = DateTime.new: "{$ymd}T00:00:00Z" or die;
my $yold = 'in the YOLD ' ~ $d.year + 1166;
my $day_of_year0 = $d.day-of-year - 1;
if $d.is-leap-year { return "St. Tib's Day, $yold" if $d.month == 2 and $d.day == 29; $day_of_year0-- if $day_of_year0 >= 60; # Compensate for St. Tib's Day }
my $weekday = @days[ $day_of_year0 mod 5 ]; my $season = @seasons[ $day_of_year0 div 73 ]; my $season_day = ordinal( $day_of_year0 mod 73 + 1 );
return "$weekday, the $season_day day of $season $yold";
}
say "$_ is {.&ddate}" for < 2010-07-22 2012-02-28 2012-02-29 2012-03-01 >; </lang>
Output:
2010-07-22 is Pungenday, the 57th day of Confusion in the YOLD 3176 2012-02-28 is Prickle-Prickle, the 59th day of Chaos in the YOLD 3178 2012-02-29 is St. Tib's Day, in the YOLD 3178 2012-03-01 is Setting Orange, the 60th day of Chaos in the YOLD 3178
PicoLisp
<lang PicoLisp>(de disdate (Year Month Day)
(let? Date (date Year Month Day) (let (Leap (date Year 2 29) D (- Date (date Year 1 1))) (if (and Leap (= 2 Month) (= 29 Day)) (pack "St. Tib's Day, YOLD " (+ Year 1166)) (and Leap (>= D 60) (dec 'D)) (pack (get '("Chaos" "Discord" "Confusion" "Bureaucracy" "The Aftermath") (inc (/ D 73)) ) " " (inc (% D 73)) ", YOLD " (+ Year 1166) ) ) ) ) )</lang>
PureBasic
<lang PureBasic>Procedure.s Discordian_Date(Y, M, D)
Protected DoY=DayOfYear(Date(Y,M,D,0,0,0)), Yold$=Str(Y+1166) Dim S.s(4) S(0)="Chaos": S(1)="Discord": S(2)="Confusion": S(3)="Bureaucracy" S(4)="The Aftermath" If (Y%4=0 And Y%100) Or Y%400=0 If M=2 And D=29 ProcedureReturn "St. Tib's Day, YOLD " + Yold$ ElseIf DoY>=2*30 DoY-1 EndIf EndIf ProcedureReturn S(DoY/73)+" "+Str(DoY%73)+", Yold "+Yold$
EndProcedure</lang>
Python
<lang python>import datetime, calendar
DISCORDIAN_SEASONS = ["Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"]
def ddate(year, month, day):
today = datetime.date(year, month, day) is_leap_year = calendar.isleap(year) if is_leap_year and month == 2 and day == 29: return "St. Tib's Day, YOLD " + (year + 1166) day_of_year = today.timetuple().tm_yday - 1 if is_leap_year and day_of_year >= 60: day_of_year -= 1 # Compensate for St. Tib's Day season, dday = divmod(day_of_year, 73) return "%s %d, YOLD %d" % (DISCORDIAN_SEASONS[season], dday + 1, year + 1166)
</lang>
REXX
<lang rexx> /*REXX program converts mm/dd/yyyy Gregorian date ───> Discordian date. */ /*Gregorian date may be m/d/yy ──or── m/d format. */
day.1='Sweetness' /*define 1st day-of-Discordian-week.*/ day.2='Boomtime' /*define 2nd day-of-Discordian-week.*/ day.3='Pungenday' /*define 3rd day-of-Discordian-week.*/ day.4='Prickle-Prickle' /*define 4th day-of-Discordian-week.*/ day.5='Setting Orange' /*define 5th day-of-Discordian-week.*/
seas.0="St. Tib's day," /*define the leap-day of Discordian yr.*/ seas.1='Chaos' /*define 1st season-of-Discordian-year.*/ seas.2='Discord' /*define 2nd season-of-Discordian-year.*/ seas.3='Confusion' /*define 3rd season-of-Discordian-year.*/ seas.4='Bureaucracy' /*define 4th season-of-Discordian-year.*/ seas.5='The Aftermath' /*define 5th season-of-Discordian-year.*/
parse arg gM '/' gD "/" gY . /*get the date specified. */ gY=left(right(date(),4),4-length(Gy))gY /*adjust for a 2-dig yr or none*/
/*below:get day-of-year,adj LeapY*/
doy=date('d',gY||right(gM,2,0)right(gD,2,0),"s")-(leapyear(gY) & gM>2) dW=doy//5;if dW==0 then dW=5 /*compute the Discordian weekday.*/ dS=(doy-1)%73+1 /*compute the Discordian season. */ dD=doy//73;if dD==0 then dD=73; dD=dD',' /*Discordian day-of-month.*/ if leapyear(gY) & gM==02 & gD==29 then do; dD=; ds=0; end /*St. Tib's?*/ say space(day.dW',' seas.dS dD gY+1166) /*show and tell Discordian date*/ exit
/*─────────────────────────────────────LEAPYEAR subroutine──────────────*/
leapyear: procedure; arg y
if y//4\==0 then return 0 /* not ≈ by 4? Not a leapyear.*/
return y//100\==0 | y//400==0 /*apply 100 and 400 year rule. */
</lang>
Output when using the inputs of:
2/28/2012
2/29/2012
3/1/2012
7/22/2010
9/2/2012
12/31/2011
Prickle-Prickle, Chaos 59, 3178 Setting Orange, St. Tib's day, 3178 Setting Orange, Chaos 60, 3178 Pungenday, Confusion 57, 3176 Setting Orange, Bureaucracy 26, 3178 Setting Orange, The Aftermath 73, 3177
Scala
<lang scala>import java.util.{GregorianCalendar, Calendar}
val DISCORDIAN_SEASONS=Array("Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath") def ddate(year:Int, month:Int, day:Int):String={
val date=new GregorianCalendar(year, month-1, day) val dyear=year+1166
val isLeapYear=date.isLeapYear(year) if(isLeapYear && month==2 && day==29) return "St. Tib's Day "+dyear+" YOLD"
var dayOfYear=date.get(Calendar.DAY_OF_YEAR) if(isLeapYear && dayOfYear>=60) dayOfYear-=1 // compensate for St. Tib's Day
val dday=dayOfYear%73 val season=dayOfYear/73 "%s %d, %d YOLD".format(DISCORDIAN_SEASONS(season), dday, dyear)
}</lang>
Tcl
<lang tcl>package require Tcl 8.5 proc disdate {year month day} {
# Get the day of the year set now [clock scan [format %02d-%02d-%04d $day $month $year] -format %d-%m-%Y] scan [clock format $now -format %j] %d doy
# Handle leap years if {!($year%4) && (($year%100) || !($year%400))} {
if {$doy == 60} { return "St. Tib's Day, [expr {$year + 1166}] YOLD" } elseif {$doy > 60} { incr doy -1 }
}
# Main conversion to discordian format now that special cases are handled incr doy -1; # Allow div/mod to work right set season [lindex {Chaos Discord Confusion Bureaucracy {The Aftermath}} \
[expr {$doy / 73}]]
set dos [expr {$doy % 73 + 1}] incr year 1166 return "$season $dos, $year YOLD"
}</lang> Demonstrating: <lang tcl>puts [disdate 2010 7 22]; # Today puts [disdate 2012 2 28] puts [disdate 2012 2 29] puts [disdate 2012 3 1]</lang> Output:
Confusion 57, 3176 YOLD Chaos 59, 3178 YOLD St. Tib's Day, 3178 YOLD Chaos 60, 3178 YOLD