# Discordian date

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.

```  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
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
if Item.Is_Tibs_Day then
else
Ada.Text_IO.Put (", " & Seasons'Image (Item.Season));
Ada.Text_IO.Put (" " & Integer'Image (Item.Day));
end if;
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>

1. DDATE.AWK - Gregorian to Discordian date contributed by Dan Nielsen
2. syntax: GAWK -f DDATE.AWK [YYYYMMDD | YYYY-MM-DD | MM-DD-YYYY | DDMMMYYYY | YYYY] ...
3. examples:
4. GAWK -f DDATE.AWK today
5. GAWK -f DDATE.AWK 20110722 one date
6. GAWK -f DDATE.AWK 20110722 20120229 two dates
7. 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("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. 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>

1. include <malloc.h>
2. include <stdlib.h>
3. include <stdio.h>
4. include <time.h>
1. define season( x ) ((x) == 0 ? "Chaos" :\
```                   (x) == 1 ? "Discord" :\
(x) == 2 ? "Confusion" :\
(x) == 3 ? "Bureaucracy" :\
"The Aftermath")
```
1. define date( x ) ((x)%73 == 0 ? 73 : (x)%73)
1. 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

Translation of: D

<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"},
```

)

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
```

<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",
}

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

Translation of: Python

<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

Translation of: Python

<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
```