Discordian date

From Rosetta Code
Task
Discordian date
You are encouraged to solve this task according to the task description, using any language you may know.


Task

Convert a given date from the   Gregorian calendar   to the   Discordian calendar.

8080 Assembly

This program is written to run under CP/M, and it takes a Gregorian date as an argument on the command line, in DDMMYYYY format.

		;; On the 44th day of Discord in the YOLD 3186, ddate
		;; has finally come to CP/M. 
bdos:		equ	5	; CP/M syscalls
puts:		equ	9
putch:		equ	2
fcb:		equ	5ch
month:		equ	fcb + 1		; use the FCB as the date argument
day:		equ	month + 2
year:		equ	day + 2
		org	100h
		;; CP/M will try to parse the command line arguments as if
		;; they are filenames. As luck would have it, MMDDYYYY is
		;; 8 characters. It would be a shame not to use this.
		lxi	h,month		; check that the 'filename' is
		lxi	b,0800h		; all digits (and zero out C)
argcheck:	mov	a,m
		call	isdigit
		jnc	argerror	; if not, give an error and exit
		inx	h
		dcr	b
		jnz	argcheck
		;; Fix the year (add 1166 to it, digit by digit)
		lxi	d,year + 3
		lxi	h,yearoffset + 3
		mvi	b,4
		ana	a		; Clear carry
yeardgt:	ldax	d		; Get digit
		adc	m		; Add offset digit
		cpi	'9' + 1		; Did we overshoot?
		cmc			; Carry is opposite of what we need
		jnc	yearnextdgt	; No carry = no adjustment 
		sui	10		; Compensate
		stc			; Carry the one
yearnextdgt:	stax	d		; Save digit
		dcx	d		; Look at more significant digit
		dcx	h		
		dcr	b		; Until we're out of digits
		jnz	yeardgt
		lxi	h,year + 4	; Terminate the year with a $
		mvi	m,'$'		; for easy output.
		;; Is it St. Tib's Day?
		lxi	d,month		; Check month and day
		lxi	h,leap		; Against '0229' 
		mvi	b,4
tibcheck:	ldax	d		; Get date byte
		cmp	m		; Match against leap day
		jnz	notibs		; No match = not Tibs
		inx	h
		inx	d
		dcr 	b
		jnz	tibcheck	; if they all match it _is_ Tibs
		;; Print "St. Tib's Day in the YOLD NNNN."
		lxi	d,tibsday
		call	outs		; fall through into printyear
		;; Print " in the YOLD NNNN."
printyear:	lxi	d,yold
		call	outs
		lxi	d,year
		jmp	outs		; if Tibs, this ends the program
		;; It isn't St. Tib's Day. We'll need to do real work :(
notibs:		lxi	h,month		; Find days at beginning of month
		call	parsenum	; (not counting Tibs)
		dcr	a		; subtract one (table is 0-indexed)
		cpi	12		; check that month < 12
		jnc	argerror	; otherwise, argument error
		ana	a		; multiply month by 2
		ral			; (entries are 2 bytes wide)
		lxi	h,monthdays	; get days table
		mov	d,c		; look up the entry (C is zero here)
		mov	e,a
		dad	d
		mov	e,m		; load the 16-bit entry into DE
		inx	h
		mov	d,m
		lxi	h,day		; Find day number
		call	parsenum
		mov	l,a		; Add it to the start of the month
		mov	h,c		; (C is still zero) - to get the day
		dad	d		; number (still not counting Tibs)
		dcx	h		; One less (so we have day numbering at 0)
		push	h		; Keep day number
		lxi	d,-365		; Make sure it isn't >365
		dad	d
		jc	argerror	; Give an error otherwise
		pop	h		; Restore day number
		push	h 		; Keep it around
		;; Calculate Erisian weekday
		lxi	d,-5		; It's not worth it being clever here
weekcalc:	dad 	d
		jc	weekcalc
		lxi	d,5
		dad	d
		mov	b,l
		lxi	h,weekdays	; Print the day of the week
		call	strselect
		lxi	d,commaday	; Print ", day "
		call	outs	
		;; Calculate season and season day number
		pop	h		; Restore day number
		mvi	b,-1		; B will be season
		lxi	d,-73		; L will be day
seasoncalc:	inr	b		; One season further on
		dad	d		; Is 73 days less
		jc 	seasoncalc 
		lxi	d,73		; Correct overshoot
		dad	d
		mov	h,b		; H:L = season:day
		inr	l		; One based for output
		push	h		; Push season and day
		mov	a,l		; Print day of season
		mvi	c,'0'-1		; Tens digit in C	
seasondgts:	inr	c
		sui	10 
		jnc	seasondgts
		adi	'0' + 10 	; Ones digit in A
		mov	e,c		; Tens digit
		call	oute
		mov	e,a		; Ones digit
		call	oute
		lxi	d,of		; Print " of "
		call	outs
		pop	b		; Retrieve season:day
		push	b 
		lxi	h,seasons	; Print the season name
		call	strselect 
		call	printyear	; "... in the YOLD NNNN ..."
		;; Is there any reason to celebrate? (day=5 or day=50)
		pop 	b		; Retrieve season:day
		mov	a,c		; Day.
		cpi	5		; is it 5?
		jz	party		; Then we party
		cpi	50 		; otherwise, is it 50?
		rnz			; If not, we're done
party:		push	b		; Keep day 
		lxi	d,celebrate	; "... Celebrate ..."
		call	outs
		pop	b		; Retrieve day
		push	b
		lxi	h,holydays5	; Get holyday from 5 or 50 table
		mov	a,c
		cpi	50
		jnz	dayname
		lxi	h,holydays50
dayname:	call	strselect	; the season is still in B
		lxi	d,xday
		pop	b		; Retrieve day once more
		mov	a,c
		cpi	50
		jnz	outs		; Print 'day' or 'flux' depending
		lxi	d,xflux
		jmp	outs
		;; Parse the 2-digit number in HL. Return in B (and A)
parsenum:	mvi	b,0		; zero accumulator
		call	parsedigit	; this runs it twice
parsedigit:	mov	a,b		; B *= 10
		add	a
		mov	b,a
		add	a
		add	a
		add	b
		add	m		; Add the digit
		sui	'0'		; Subtract '0'
		mov	b,a
		inx	h
		ret
		;; Print the B'th string from HL
strselect:	mvi	a,'$'
strsearcho:	dcr	b
		jm	strfound
strsearchi:	cmp	m
		inx	h
		jnz	strsearchi
		jmp	strsearcho
strfound:	xchg
		jmp	outs
		;; Print the argument error, and exit
argerror:	lxi	d,argfmt
		;; Print the string in DE and exit
error:		call	outs
		rst	0
		;; Returns with carry flag set if A is a digit ('0'-'9'). 
isdigit:	cpi	'0'
		cmc
		rnc
		cpi	'9' + 1
		ret 
		;; Print the string in D.
outs:		mvi	c,puts
		jmp	bdos
		;; Print character in E, keeping registers.
oute:		push	psw
		push	b
		push 	d
		push	h
		mvi	c,putch
		call	bdos
		pop	h
		pop	d
		pop	b
		pop	psw
		ret 
		;; Accumulated days at start of Gregorian months
		;; (in a non-leap year)
monthdays:	dw	0,31,59,90,120,151,181,212,243,273,304,334
		;; Difference between Gregorian and Erisian year count
		;; (we don't need to bother with the year otherwise)
yearoffset:	db	1,1,6,6
		;; This is matched to MMDD to handle St. Tib's Day
leap:		db	'0229'
		;; Strings
argfmt:		db	'DDATE MMDDYYYY$'
weekdays:	db	'Sweetmorn$Boomtime$Pungenday$Prickle-Prickle$'
		db	'Setting Orange$'
commaday:	db	', day $'
of:		db	' of $'
seasons:	db	'Chaos$Discord$Confusion$Bureaucracy$The Aftermath$'
celebrate:	db	': celebrate $'
holydays5:	db	'Mung$Mojo$Sya$Zara$Mala$'
xday:		db	'day!$'
holydays50:	db	'Chao$Disco$Confu$Bure$Af$'		
xflux:		db	'flux!$'
tibsday:	db	'Saint Tib',39,'s Day$'
yold:		db	' in the YOLD $'
Output:
A>ddate 04272020
Boomtime, day 44 of Discord in the YOLD 3186
A>ddate 09261995
Prickle-Prickle, day 50 of Bureaucracy in the YOLD 3161: celebrate Bureflux!
A>ddate 02291996
Saint Tib's Day in the YOLD 3162
A>ddate 07222011
Pungenday, day 57 of Confusion in the YOLD 3177
A>ddate 01052005
Setting Orange, day 05 of Chaos in the YOLD 3171: celebrate Mungday!

8086 Assembly

Translation of: 8080 Assembly

This program runs under DOS. It can take a date on the command line in the form MM/DD/YYYY, and if a date is not given, it asks DOS for the system date and uses that instead. It is mostly a port of the 8080 (CP/M) version, but it does use the 8086's new capabilities where possible, e.g. multiplication and division, and the string lookups are done using an 8086 string instruction.

This code is written to compile to a .COM file using nasm.

		;; DDATE for MS-DOS (assembles using nasm)
		bits	16		
		cpu	8086
tlength:	equ	80h
cmdtail:	equ	81h
putch:		equ	2
puts:		equ	9 
getdate:	equ	2Ah 
		org	100h
section		.text
		;; Check if a date was given
		mov	bl,[tlength]	; Length of command line
		and	bl,bl		; Is it zero?
		jz	gettoday	; Then get today's date 
		;; Parse the date given on the command line
		cmp	bl,10+1		; MM/DD/YYYY is ten characters long
		jne	printusage	; If it doesn't match, print usage.
		xor	bh,bh
		add 	bx,cmdtail
		mov	byte [bx],0	; Zero terminate the date 
		mov	si,cmdtail+1	; Get month,
		call	atoi
		mov	dh,al		; store in DH,
		inc	si		; get day,
		call	atoi
		mov 	dl,al		; store in DL,
		inc	si		; get year,
		call	atoi
		mov	cx,ax		; and store in CX.
		jmp	convertdate
		;; Ask MS-DOS for the date
gettoday:	mov	ah,puts		; Prefix output with 'Today is '
		mov	dx,todayis
		int	21h
		mov	ah,getdate	; And get the current date.
		int	21h
		;; Convert the date to the Discordian calendar
		;; (DL=day, DH=month, CX=year)
convertdate:	add	cx,1166		; Erisian year is 1166 years onwards.
		cmp 	dx,21dh		; Is it St. Tib's Day?
		jne	notibs
		mov	dx,tibsday 	; If yes, print "St. Tib's Day"
		mov	ah,puts
		int	21h
		;; Print "in the YOLD NNNN" and then end.
intheyold:	mov	dx,yold		; In the YOLD
		mov	ah,puts
		int	21h
		mov	ax,cx		; print the year
		call	printn
		ret			; If Tibs, this ends the program.
		;; It isn't St. Tib's Day.
notibs:		cmp	dh,1		; Month < 1 = error
		jb	printinval
		cmp	dl,1		; Day < 1 = error
		jb	printinval
		cmp	dh,12		; Month > 12 = error
		ja	printinval
		mov	bx,monthlengths-1
		xor	ah,ah		; Day higher than it should be
		mov	al,dh		; (according to month table)
		add	bx,ax		; = error
		cmp	dl,[bx]
		ja	printinval
		mov	bx,monthdays-2	; Calculate day of year
		mov	al,dh		; Cumulative months
		sal	al,1		; Multiply by 2 (2 bits per entry)
		add	bx,ax
		mov	ax,[bx]		; Days since start of month
		xor	dh,dh
		add	dx,ax		; Add day of month
		dec	dx		; Start at 0 (For array lookup)
		mov	ax,dx		; Get weekday
		mov	bl,5		; Divide by 5
		div	bl		; AH = weekday (modulo)
		mov	bl,ah
		mov	di,weekdays
		call	strselect	; Print the weekday
		mov	bx,dx		; Keep day of year in bx for now
		mov	dx,commaday	; ... ', day '
		call	printstr
		mov	dl,73		; Each season is 73 days long
		mov	ax,bx		; Divide day of year by 73
		div	dl		; DH=AH=day of season (modulo)	
		mov	dx,ax		; DL=AL=season number
		xor	ah,ah		; Print day of season
		mov	al,dh
		inc	al		; One more (days do start at 1)
		call	printn
		mov	bx,dx		; Store day and season in bx
		mov	dx,of		; Print ... ' of '
		call	printstr
		mov	dx,bx		; Day and season in dx again
		mov	di,seasons	; Print season
		call	strselect	; BL is still season number
		mov	bx,dx		; Day and season in BX again.
		call	intheyold	; Print the year 
		cmp	bh,5-1		; Something to celebrate?
		je	party		; (Day 5 or 50?
		cmp	bh,50-1
		je	party
		ret			; If not, stop.
party:		mov	al,bh		; Day in AL.
		mov	bx,holydays5	; Day 5 holydays.
		mov	cx,xday	
		cmp	al,50-1		; Unless it's 50
		jne	holyday
		mov	bx,holydays50	; Then we need day 50 holydays.
		mov	cx,xflux
holyday:	mov	dx,celebrate	; Print ... ', celebrate: '
		call	printstr
		mov	dx,bx
		call	printstr
		mov	dx,cx
		jmp	printstr
		;; Print "invalid date".
printinval:	mov	dx,inval
		jmp	printstr 
		;; Print usage.
printusage:	mov	dx,usage
		;; Print DX.
printstr:	mov	ah,puts
		int	21h
		ret
		;; Subroutine: print the BL'th string from DI
strselect:	inc	bl		; Counter the 'dec bl' later 
		mov	al,'$'		; String end
		push	cx		; Keep registers
		push	dx
.search		dec	bl		; Are we there yet?
		jz	.found
		mov	cx,-1		
		repne	scasb 		; Scan to end of string
		jmp	.search
.found		mov	dx,di		; Found the string, print it
		mov	ah,puts
		int	21h
		pop	dx		; Restore registers
		pop	cx
		ret
		;; Subroutine: print number in AX.
printn:		push	cx		; Don't trample registers
		push	dx
		mov	si,numend 	; End of number string.
		mov	cx,10 		; Divisor, ten.
.loop		xor	dx,dx		; Zero DX.
		dec	si		; Back up one digit.
		div	cx		; Divide AX by ten.
		add	dl,'0'		; Remainder is now in DX; make ASCII
		mov	[si],dl		; and store.
		and	ax,ax		; Quotient is in AX, check if zero
		jnz	.loop 		; loop for next digit if there is one.
		mov	dx,si		; Print SI - move it to DX,
		mov	ah,puts		; and then call the DOS print function
		int	21h
		pop	dx		; Restore the registers
		pop	cx
		ret
		;; Subroutine: parse number at [SI], store in AX.
atoi:		push	bx		; Don't trample registers
		push	cx
		push	dx
		xor	ax,ax		; Zero AX.
		xor	bh,bh		; BH as well.
		mov	cx,10		; Multiplier, ten.
.loop		mov	bl,[si]		; Current number.
		sub	bl,'0'		; Subtract '0'.
		jc	.done		; If <0, then done.
		cmp	bl,9		; If it's higher than 9,
		jnbe	.done		; also done.
		mul	cx		; Multiply accumulator by 10
		add	ax,bx		; Add the digit in.
		inc	si		; Next digit
		jmp	.loop
.done		pop	dx		; Restore registers
		pop	cx
		pop	bx
		ret
section		.data		
		;; Accumulated days at start of Gregorian months
monthdays:	dw	0,31,59,90,120,151,181,212,243,273,304,334
		;; Days per month
monthlengths:	db	31,28,31,30,31,30,31,31,30,31,30,31
		;; Strings
inval:		db	'Invalid date.$'
usage:		db	`DDATE [MM/DD/YYYY]\r\n`
		db	`\r\n\tPrint today's date or the given date in the`
		db	` Discordian calendar.$`
number:		db	'00000'
numend:		db	'$'		
todayis:	db	'Today is $'
weekdays:	db	'Sweetmorn$Boomtime$Pungenday$Prickle-Prickle$'
		db	'Setting Orange$'
commaday:	db	', day $'
of:		db	' of $'
seasons:	db	'Chaos$Discord$Confusion$Bureaucracy$The Aftermath$'
celebrate:	db	': celebrate $'
holydays5:	db	'Mung$Mojo$Sya$Zara$Mala$'
xday:		db	'day!$'
holydays50:	db	'Chao$Disco$Confu$Bure$Af$'		
xflux:		db	'flux!$'
tibsday:	db	"Saint Tib's Day$"
yold:		db	' in the YOLD $'
Output:
C:\>ddate
Today is Pungenday, day 50 of Discord in the YOLD 3186: celebrate Chaoflux!
C:\>ddate 09/26/1995
Prickle-Pricke, day 50 of Bureaucracy in the YOLD 3161: celebrate Chaoflux!
C:\>ddate 02/29/1996
Saint Tib's Day in the YOLD 3162
C:\>ddate 07/22/2011
Pungenday, day 57 of Confusion in the YOLD 3177
C:\>ddate 01/05/2005
Setting Orange, day 5 of Chaos in the YOLD 3171: celebrate Mungday!

Action!

Translation of: MAD
...via PL/M
;;; Discordian date calculation - translation of MAD (via PL/M)

;;; returns the next number from line, the terminator is ignored
;;;         pos holds the position in line and is updated to the
;;;             position of the character following the trailing
;;;             delimiter - if there is one
;;;             pos should be set to 1 on rhe first call
INT FUNC getNumber( CHAR ARRAY line, CARD POINTER pos )
  CARD value, linePos

  linePos = pos^
  value   = 0
  ; skip spaces
  WHILE linePos <= line(0) AND line(linePos) = '  DO linePos ==+ 1 OD
  ; get the number
  WHILE linePos <= line(0) AND line(linePos) >= '0 AND line(linePos) <= '9
  DO
    value   ==* 10
    value   ==+ (line(linePos) - '0)
    linePos ==+ 1
  OD
  pos^ = linePos + 1
RETURN(value)

;;; get a Gregorian date and output it as a Discordian date
PROC Main()

  DEFINE STRING_POINTER = "CARD"

  CARD gMonth, gDay, gYear, gPos
  CARD yrDay, season, day, wkDay
  CHAR ARRAY gLine(256)
  STRING_POINTER ARRAY holy5(5), holy50(5), disday(5), disssn(5)
  INT ARRAY mlengt(13) = [   0   0  31  59  90 120
                           151 181 212 243 273 304 334
                         ]
  holy5 (0) = "MUNG"           holy5 (1) = "MOJO"  holy5 (2) = "SYA"
  holy5 (3) = "ZARA"           holy5 (4) = "MALA"
  holy50(0) = "CHAO"           holy50(1) = "DISCO" holy50(2) = "CONFU"
  holy50(3) = "BURE"           holy50(4) = "AF"
  disday(0) = "SWEETMORN"      disday(1) = "BOOMTIME"
  disday(2) = "PUNGENDAY"      disday(3) = "PRICKLE-PRICKLE"
  disday(4) = "SETTING ORANGE"
  disssn(0) = "CHAOS"          disssn(1) = "DISCORD" disssn(2) = "CONFUSION"
  disssn(3) = "BUREAUCRACY"    disssn(4) = "THE AFTERMATH" 

  ; get the Gregorian date from the keyboard, NB: no validation
  Print("Gregorian date (MM/DD/YYYY)> ")
  InputS(gLine)
  gPos   = 1
  gMonth = getNumber(gLine, @gPos)
  gDay   = getNumber(gLine, @gPos)
  gYear  = getNumber(gLine, @gPos)

  ; convert to Discordian
  IF gMonth = 2 AND gDay = 29 THEN
    Print("SAINT TIB'S DAY IN THE Y.O.L.D. ")PrintC(gYear+1166)
  ELSE
    yrDay  = mlengt(gMonth)+gDay
    season = yrDay/73
    day    = yrDay-season*73
    wkDay  = (yrDay-1) MOD 5
    Print(disday(wkDay) )Print(", DAY ")PrintC(day)Print(" OF ")
    Print(disssn(season))Print(" IN THE Y.O.L.D ")PrintC(gYear+1166)
    IF     day =  5 THEN
      PutE()
      Print("CELEBRATE ")Print(holy5(season))Print("DAY")
    ELSEIF day = 50 THEN
      PutE()
      Print("CELEBRATE ")Print(holy50(season))Print("FLUX")
    FI
  FI
  PutE()

RETURN
Output:
Gregorian date (MM/DD/YYYY)> 4/1/2023
SWEETMORN, DAY 18 OF DISCORD IN THE Y.O.L.D 3189

Ada

discordian.adb:

with Ada.Calendar.Arithmetic;
with Ada.Text_IO;
with Ada.Integer_Text_IO;
with Ada.Strings.Unbounded;
with Ada.Strings.Unbounded.Text_IO;
with Ada.Command_Line;

procedure Discordian is
   use Ada.Calendar;
   use Ada.Strings.Unbounded;
   use Ada.Command_Line;
   package UStr_IO renames Ada.Strings.Unbounded.Text_IO;

   subtype Year_Number is Integer range 3067 .. 3565;
   type Seasons is (Chaos, Discord, Confusion, Bureaucracy, The_Aftermath);
   type Days_Of_Week is (Sweetmorn, Boomtime, Pungenday,
                         Prickle_Prickle, Setting_Orange);
   subtype Day_Number is Integer range 1 .. 73;
 
   type Discordian_Date is record
      Year        : Year_Number;
      Season      : Seasons;
      Day         : Day_Number;
      Week_Day    : Days_Of_Week;
      Is_Tibs_Day : Boolean := False;
   end record;

   function Week_Day_To_Str(Day : Days_Of_Week) return Unbounded_String is
      s : Unbounded_String;
   begin
      case Day is
         when Sweetmorn       => s := To_Unbounded_String("Sweetmorn");
         when Boomtime        => s := To_Unbounded_String("Boomtime");
         when Pungenday       => s := To_Unbounded_String("Pungenday");
         when Prickle_Prickle => s := To_Unbounded_String("Prickle-Prickle");
         when Setting_Orange  => s := To_Unbounded_String("Setting Orange");
      end case;
      return s;
   end Week_Day_To_Str;

   function Holiday(Season: Seasons) return Unbounded_String is
      s : Unbounded_String;
   begin
      case Season is
         when Chaos         => s := To_Unbounded_String("Chaoflux");
         when Discord       => s := To_Unbounded_String("Discoflux");
         when Confusion     => s := To_Unbounded_String("Confuflux");
         when Bureaucracy   => s := To_Unbounded_String("Bureflux");
         when The_Aftermath => s := To_Unbounded_String("Afflux");
      end case;
      return s;
   end Holiday;

   function Apostle(Season: Seasons) return Unbounded_String is
      s : Unbounded_String;
   begin
      case Season is
         when Chaos         => s := To_Unbounded_String("Mungday");
         when Discord       => s := To_Unbounded_String("Mojoday");
         when Confusion     => s := To_Unbounded_String("Syaday");
         when Bureaucracy   => s := To_Unbounded_String("Zaraday");
         when The_Aftermath => s := To_Unbounded_String("Maladay");
      end case;
      return s;
   end Apostle;

   function Season_To_Str(Season: Seasons) return Unbounded_String is
      s : Unbounded_String;
   begin
      case Season is
         when Chaos         => s := To_Unbounded_String("Chaos");
         when Discord       => s := To_Unbounded_String("Discord");
         when Confusion     => s := To_Unbounded_String("Confusion");
         when Bureaucracy   => s := To_Unbounded_String("Bureaucracy");
         when The_Aftermath => s := To_Unbounded_String("The Aftermath");
      end case;
      return s;
   end Season_To_Str;

   procedure Convert (From : Time; To : out Discordian_Date) is
      use Ada.Calendar.Arithmetic;
      First_Day   : Time;
      Number_Days : Day_Count;
      Leap_Year   : boolean;
   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;
      Leap_Year := False;
      if Year (Date => From) mod 4 = 0 then
          if Year (Date => From) mod 100 = 0 then
              if Year (Date => From) mod 400 = 0 then
                  Leap_Year := True;
              end if;
          else
              Leap_Year := True;
          end if;
      end if;
      if Leap_Year 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;
      case Number_Days mod 5 is
         when 0 => To.Week_Day := Sweetmorn;
         when 1 => To.Week_Day := Boomtime;
         when 2 => To.Week_Day := Pungenday;
         when 3 => To.Week_Day := Prickle_Prickle;
         when 4 => To.Week_Day := Setting_Orange;
         when others => raise Constraint_Error;
      end case;
   end Convert;
 
   procedure Put (Item : Discordian_Date) is
   begin
      if Item.Is_Tibs_Day then
         Ada.Text_IO.Put ("St. Tib's Day");
      else
         UStr_IO.Put (Week_Day_To_Str(Item.Week_Day));
         Ada.Text_IO.Put (", day" & Integer'Image (Item.Day));
         Ada.Text_IO.Put (" of ");
         UStr_IO.Put (Season_To_Str (Item.Season));
         if Item.Day = 5 then
            Ada.Text_IO.Put (", ");
            UStr_IO.Put (Apostle(Item.Season));
         elsif Item.Day = 50 then
            Ada.Text_IO.Put (", ");
            UStr_IO.Put (Holiday(Item.Season));
         end if;
      end if;
      Ada.Text_IO.Put (" in the YOLD" & Integer'Image (Item.Year));
      Ada.Text_IO.New_Line;
   end Put;
 
   Test_Day  : Time;
   Test_DDay : Discordian_Date;
   Year : Integer;
   Month : Integer;
   Day : Integer;
   YYYYMMDD : Integer;
begin

   if Argument_Count = 0 then
      Test_Day := Clock;
      Convert (From => Test_Day, To => Test_DDay);
      Put (Test_DDay);
   end if;

   for Arg in 1..Argument_Count loop

      if Argument(Arg)'Length < 8 then
         Ada.Text_IO.Put("ERROR: Invalid Argument : '" & Argument(Arg) & "'");
         Ada.Text_IO.Put("Input format YYYYMMDD");
         raise Constraint_Error;
      end if;

      begin
         YYYYMMDD := Integer'Value(Argument(Arg));
      exception
         when Constraint_Error =>
            Ada.Text_IO.Put("ERROR: Invalid Argument : '" & Argument(Arg) & "'");
            raise;
      end;

      Day := YYYYMMDD mod 100;
      if Day < Day_Number'First or Day > Day_Number'Last then
         Ada.Text_IO.Put("ERROR: Invalid Day:" & Integer'Image(Day));
         raise Constraint_Error;
      end if;

      Month := ((YYYYMMDD - Day) / 100) mod 100;
      if Month < Month_Number'First or Month > Month_Number'Last then
         Ada.Text_IO.Put("ERROR: Invalid Month:" & Integer'Image(Month));
         raise Constraint_Error;
      end if;

      Year := ((YYYYMMDD - Day - Month * 100) / 10000);
      if Year < 1901 or Year > 2399 then
         Ada.Text_IO.Put("ERROR: Invalid Year:" & Integer'Image(Year));
         raise Constraint_Error;
      end if;

      Test_Day := Time_Of (Year => Year, Month => Month, Day => Day);

      Convert (From => Test_Day, To => Test_DDay);
      Put (Test_DDay);

   end loop;

end Discordian;
Output:
$ ./discordian 21001231 20120228 20120229 20120301 20100722 20120902 20121231
Setting Orange, day 73 of The Aftermath in the YOLD 3266
Prickle-Prickle, day 59 of Chaos in the YOLD 3178
St. Tib's Day in the YOLD 3178
Setting Orange, day 60 of Chaos in the YOLD 3178
Pungenday, day 57 of Confusion in the YOLD 3176
Setting Orange, day 26 of Bureaucracy in the YOLD 3178
Setting Orange, day 73 of The Aftermath in the YOLD 3178

ALGOL 68

Translation of: ALGOL W
which was itself,
Translation of: MAD

Algol 68 has variable length strings which simplifies this a lot relative to the Algol W version.

BEGIN #   DISCORDIAN DATE CALCULATION - TRANSLATION OF MAD VIA ALGOL W    #
    INT      greg, gmonth, gday, gyear;
    []STRING holys  = []STRING( "MUNG", "MOJO",  "SYA",   "ZARA", "MALA" )[ AT 0 ];
    []STRING holys0 = []STRING( "CHAO", "DISCO", "CONFU", "BURE", "AF"   )[ AT 0 ];
    []STRING disday = []STRING( "SWEETMORN", "BOOMTIME", "PUNGENday", "PRICKLE-PRICKLE", "SETTING ORANGE" )[ AT 0 ];
    []STRING disssn = []STRING( "CHAOS",     "DISCORD",  "CONFUSION", "BUREAUCRACY",     "THE AFTERMATH"  )[ AT 0 ];
    []INT    mlengt = []INT( 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 )[ AT 0 ];
    CHAR     slash1, slash2;
 
    # input date should contain MM/DD/YYYY in the gregorian calendar      #
    read( ( gmonth, slash1, gday, slash2, gyear ) );  
    IF slash1 /= "/" OR slash2 /= "/" THEN print( ( "Invalid date format", newline ) ); stop FI;

    IF gmonth = 2 AND gday = 29
    THEN print( ( "SAINT TIB'S DAY IN THE Y.O.L.D. ", whole( gyear + 1166, -4 ), newline ) )
    ELSE 
        INT yrday  := mlengt[ gmonth ] + gday;
        INT season := yrday OVER 73;
        INT day    := yrday - ( season * 73 );
        INT wkday  := ( yrday - 1 ) MOD 5;
        print( ( disday[ wkday ], ", DAY ", whole( day, -2 ), " OF ", disssn[ season ]
               , " IN THE Y.O.L.D ", whole( gyear + 1166, 0 ), newline
               )
             );
        IF   day = 5  THEN print( ( "CELEBRATE ", holys[  season ], "DAY"  ) )
        ELIF day = 50 THEN print( ( "CELEBRATE ", holys0[ season ], "FLUX" ) )
        FI
    FI
END
Output:
11/04/1167
PUNGENday, day 16 OF THE AFTERMATH IN THE Y.O.L.D 2333

08/15/2017
BOOMTIME, DAY  8 OF BUREAUCRACY IN THE Y.O.L.D 3183

12/06/2020
SETTING ORANGE, DAY 48 OF THE AFTERMATH IN THE Y.O.L.D 3186

07/12/1969
PUNGENday, DAY 47 OF CONFUSION IN THE Y.O.L.D 3135

07/05/2005
SWEETMORN, DAY 40 OF CONFUSION IN THE Y.O.L.D 3171

09/26/1995
PRICKLE-PRICKLE, DAY 50 OF BUREAUCRACY IN THE Y.O.L.D 3161
CELEBRATE BUREFLUX

11/30/2021
PRICKLE-PRICKLE, DAY 42 OF THE AFTERMATH IN THE Y.O.L.D 3187

ALGOL W

Translation of: MAD

Algol W doesn't have the array initialisation equivalent of MAD's VECTOR VALUES and also does not allow implicit declarations. Algol W does not have I/O formsts or variable length strings in output, which makes this version somewhat longer.

BEGIN %   DISCORDIAN DATE CALCULATION - TRANSLATION OF MAD                %
    INTEGER          GREG, GMONTH, GDAY, GYEAR;
    STRING(16) ARRAY HOLY5  ( 0 ::  4 );
    STRING(16) ARRAY HOLY50 ( 0 ::  4 );
    STRING(16) ARRAY DISDAY ( 0 ::  4 );
    STRING(16) ARRAY DISSSN ( 0 ::  4 );
    INTEGER    ARRAY MLENGT ( 0 :: 12 );
    INTEGER          APOS;
    STRING(1)        SLASH1, SLASH2;

    % WRITES A "$" TERMINATED STRING                                      %
    PROCEDURE WRITEONTEXT( STRING(16) VALUE TEXT ) ;
    BEGIN
        INTEGER TPOS;
        TPOS := 0;
        WHILE TPOS < 16 DO BEGIN
            IF TEXT( TPOS // 1 ) = "$"
            THEN TPOS := 32
            ELSE WRITEON( TEXT( TPOS // 1 ) );
            ;
            TPOS := TPOS + 1
        END WHILE_TPOS_LT_16
    END WRITEONTEXT;

    APOS := 0;
    FOR M := 0,0,31,59,90,120,151,181,212,243,273,304,334 DO BEGIN MLENGT(APOS) := M; APOS := APOS + 1 END;
    HOLY5 (0) := "MUNG$";HOLY5 (1) := "MOJO$"; HOLY5 (2) := "SYA$";  HOLY5 (3) := "ZARA$"; HOLY5 (4) := "MALA$";
    HOLY50(0) := "CHAO$";HOLY50(1) := "DISCO$";HOLY50(2) := "CONFU$";HOLY50(3) := "BURE$"; HOLY50(4) := "AF$";
    DISDAY(0) := "SWEETMORN$";       DISDAY(1) := "BOOMTIME$";      DISDAY(2) := "PUNGENDAY$";
    DISDAY(3) := "PRICKLE-PRICKLE$"; DISDAY(4) := "SETTING ORANGE$";
    DISSSN(0) := "CHAOS$"; DISSSN(1) := "DISCORD$"; DISSSN(2) := "CONFUSION$";
    DISSSN(3) := "BUREAUCRACY$"; DISSSN(4) := "THE AFTERMATH$"; 

    % INPUT DATE SHOULD CONTAIN MM/DD/YYYY IN GREGORIAN CALENDAR          %
    READ( GMONTH, SLASH1, GDAY, SLASH2, GYEAR );  
 
    IF GMONTH = 2 AND GDAY = 29
    THEN WRITE( I_W := 4, S_W := 0, "SAINT TIB'S DAY IN THE Y.O.L.D. ", GYEAR + 1166 )
    ELSE BEGIN
        INTEGER YRDAY, SEASON, DAY, WKDAY;
        YRDAY  := MLENGT(GMONTH)+GDAY;
        SEASON := YRDAY DIV 73;
        DAY    := YRDAY-SEASON*73;
        WKDAY  := (YRDAY-1) REM 5;
        WRITEONTEXT( DISDAY(WKDAY) );
        WRITEON( S_W := 0, ", DAY ", I_W := 2, DAY, " OF " );
        WRITEONTEXT( DISSSN(SEASON) );
        WRITEON( S_W := 0, " IN THE Y.O.L.D ", I_W := 4, GYEAR + 1166 );
        IF      DAY = 5  THEN BEGIN
            WRITE( "CELEBRATE " );WRITEONTEXT( HOLY5(SEASON) );  WRITEON( "DAY"  )
            END
        ELSE IF DAY = 50 THEN BEGIN
            WRITE( "CELEBRATE " );WRITEONTEXT( HOLY50(SEASON) ); WRITEON( "FLUX" )
        END IF_FAY_EQ_5__DAY_EQ_50
    END
END.
Output:
08/15/2017
BOOMTIME, DAY  8 OF BUREAUCRACY IN THE Y.O.L.D 3183

12/06/2020
SETTING ORANGE, DAY 48 OF THE AFTERMATH IN THE Y.O.L.D 3186

07/12/1969
PUNGENDAY, DAY 47 OF CONFUSION IN THE Y.O.L.D 3135

01/05/2005
SETTING ORANGE, DAY  5 OF CHAOS IN THE Y.O.L.D 3171
CELEBRATE MUNGDAY

09/26/1995
PRICKLE-PRICKLE, DAY 50 OF BUREAUCRACY IN THE Y.O.L.D 3161
CELEBRATE BUREFLUX

AppleScript

on gregorianToDiscordian(inputDate) -- Input: AppleScript date object.
    (*
        Discordian years are aligned with, and the same length as, Gregorian years.
        Each has 73 5-day weeks and 5 73-day seasons. (73 * 5 = 365.)
        The first day of a Discordian year is also that of its first week and first season.
        In leap years, an extra day called "St. Tib's Day", is inserted between days 59 and 60.
        It's considered to be outside the calendar, so the day after it is Setting Orange, Chaos 60,
        not Sweetmorn, Chaos 61. Year 1 YOLD is 1166 BC, but this handler takes an AS date object
        as its input and is only good for AD Gregorian dates. Since the Discordian calendar's an
        American invention, the output here's in the US style: "Weekday, Season day, year".
    *)
    -- Calculate the input date's day-of-year number.
    copy inputDate to startOfYear
    tell startOfYear to set {its day, its month} to {1, January}
    set dayOfYear to (inputDate - startOfYear) div days + 1
    
    -- If it's a leap year, special-case St. Tib's Day, or adjust the day-of-year number if the day comes after that.
    set y to inputDate's year
    if ((y mod 4 is 0) and ((y mod 100 > 0) or (y mod 400 is 0))) then
        if (dayOfYear is 60) then
            set dayOfYear to "St. Tib's Day"
        else if (dayOfYear > 60) then
            set dayOfYear to dayOfYear - 1
        end if
    end if
    
    -- Start the output text with either "St. Tib's Day" or the weekday, season, and day-of-season number.
    if (dayOfYear is "St. Tib's Day") then
        set outputText to dayOfYear
    else
        tell dayOfYear - 1
            set dayOfWeek to it mod 5 + 1
            set seasonNumber to it div 73 + 1
            set dayOfSeason to it mod 73 + 1
        end tell
        set theWeekdays to {"Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange"}
        set theSeasons to {"Chaos ", "Discord ", "Confusion ", "Bureaucracy ", "The Aftermath "}
        set outputText to (item dayOfWeek of theWeekdays) & ", " & (item seasonNumber of theSeasons) & dayOfSeason
    end if
    
    -- Append the Discordian year number and return the result.
    return outputText & ", " & (y + 1166)
end gregorianToDiscordian

set ASDate to (current date)
set gregorianDate to ASDate's date string
set discordianDate to gregorianToDiscordian(ASDate)
return {Gregorian:gregorianDate, Discordian:discordianDate}
Output:
{Gregorian:"Saturday 5 December 2020", Discordian:"Prickle-Prickle, The Aftermath 47, 3186"}

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(  arr,cmd,d,x) { # under Microsoft Windows
# XP - The current date is: MM/DD/YYYY
# 8  - The current date is: DOW MM/DD/YYYY
    cmd = "DATE <NUL"
    cmd | getline x
    close(cmd) # close pipe
    d = arr[split(x,arr," ")]
    return sprintf("%04d%02d%02d",substr(d,7,4),substr(d,1,2),substr(d,4,2))
}
function error(x) {
    printf("error: argument %d is invalid, %s, in %s\n",argno,ARGV[argno],x)
    errors++
}
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

BASIC

Works with: FreeBASIC
Translation of: PowerBASIC
#INCLUDE "datetime.bi"

DECLARE FUNCTION julian(AS DOUBLE) AS INTEGER

SeasonNames:
DATA "Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"
Weekdays:
DATA "Setting Orange", "Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle"
DaysPreceding1stOfMonth:
'   jan feb mar apr may  jun  jul  aug  sep  oct  nov  dec
DATA 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334

DIM dyear AS INTEGER, dseason AS STRING, dday AS INTEGER, dweekday AS STRING
DIM tmpdate AS DOUBLE, jday AS INTEGER, result AS STRING
DIM L0 AS INTEGER

IF LEN(COMMAND$) THEN
    tmpdate = DATEVALUE(COMMAND$)
ELSE
    tmpdate = FIX(NOW())
END IF
dyear = YEAR(tmpdate) + 1166
IF (2 = MONTH(tmpdate)) AND (29 = DAY(tmpdate)) THEN
    result = "Saint Tib's Day, " & STR$(dyear) & " YOLD"
ELSE
    jday = julian(tmpdate)
    RESTORE SeasonNames
    FOR L0 = 1 TO ((jday - 1) \ 73) + 1
    	READ dseason
    NEXT
    dday = (jday MOD 73)
    IF 0 = dday THEN dday = 73
    RESTORE Weekdays
    FOR L0 = 1 TO (jday MOD 5) + 1
        READ dweekday
    NEXT
    result = dweekday & ", " & dseason & " " & TRIM$(STR$(dday)) & ", " & TRIM$(STR$(dyear)) & " YOLD"
END IF

? result
END

FUNCTION julian(d AS DOUBLE) AS INTEGER
    'doesn't account for leap years (not needed for ddate)
    DIM tmp AS INTEGER, L1 AS INTEGER
    RESTORE DaysPreceding1stOfMonth
    FOR L1 = 1 TO MONTH(d)
        READ tmp
    NEXT
    FUNCTION = tmp + DAY(d)
END FUNCTION
Output:
"Discordian date.exe" 19-10-2015 
Boomtime, Bureaucracy 73, 3181 YOLD

Batch File

@echo off
goto Parse

 Discordian Date Converter:
 
 Usage:
	ddate 
	ddate /v 
	ddate /d isoDate
	ddate /v /d isoDate
 
:Parse
	shift 
	if "%0"==""   goto Prologue
	if "%0"=="/v" set Verbose=1
	if "%0"=="/d" set dateToTest=%1
	if "%0"=="/d" shift
goto Parse

:Prologue
	if "%dateToTest%"=="" set dateToTest=%date%
	for %%a in (GYear GMonth GDay GMonthName GWeekday GDayThisYear) do set %%a=fnord
	for %%a in (DYear DMonth DDay DMonthName DWeekday) do set %%a=MUNG
goto Start

:Start
	for /f "tokens=1,2,3 delims=/:;-. " %%a in ('echo %dateToTest%') do (
		set GYear=%%a
		set GMonth=%%b
		set GDay=%%c
	)
goto GMonthName

:GMonthName
	if %GMonth% EQU  1	set GMonthName=January
	if %GMonth% EQU  2	set GMonthName=February
	if %GMonth% EQU  3	set GMonthName=March
	if %GMonth% EQU  4	set GMonthName=April
	if %GMonth% EQU  5	set GMonthName=May
	if %GMonth% EQU  6	set GMonthName=June
	if %GMonth% EQU  7	set GMonthName=July
	if %GMonth% EQU  8	set GMonthName=August
	if %GMonth% EQU  9	set GMonthName=September
	if %GMonth% EQU 10	set GMonthName=October
	if %GMonth% EQU 11	set GMonthName=November
	if %GMonth% EQU 12	set GMonthName=December
goto GLeap

:GLeap
	set /a CommonYear=GYear %% 4
	set /a CommonCent=GYear %% 100
	set /a CommonQuad=GYear %% 400
	set GLeap=0
	if %CommonYear% EQU 0 set GLeap=1
	if %CommonCent% EQU 0 set GLeap=0
	if %CommonQuad% EQU 0 set GLeap=1
goto GDayThisYear

:GDayThisYear
	set GDayThisYear=%GDay%
	if %GMonth% GTR 11                  set /a GDayThisYear=%GDayThisYear%+30
	if %GMonth% GTR 10                  set /a GDayThisYear=%GDayThisYear%+31
	if %GMonth% GTR  9                  set /a GDayThisYear=%GDayThisYear%+30
	if %GMonth% GTR  8                  set /a GDayThisYear=%GDayThisYear%+31
	if %GMonth% GTR  7                  set /a GDayThisYear=%GDayThisYear%+31
	if %GMonth% GTR  6                  set /a GDayThisYear=%GDayThisYear%+30
	if %GMonth% GTR  5                  set /a GDayThisYear=%GDayThisYear%+31
	if %GMonth% GTR  4                  set /a GDayThisYear=%GDayThisYear%+30
	if %GMonth% GTR  3                  set /a GDayThisYear=%GDayThisYear%+31
	if %GMonth% GTR  2 if %GLeap% EQU 1 set /a GDayThisYear=%GDayThisYear%+29
	if %GMonth% GTR  2 if %GLeap% EQU 0 set /a GDayThisYear=%GDayThisYear%+28
	if %GMonth% GTR  1                  set /a GDayThisYear=%GDayThisYear%+31
goto DYear

:DYear
	set /a DYear=GYear+1166
goto DMonth

:DMonth
	set DMonth=1
	set DDay=%GDayThisYear%
	if %DDay% GTR 73 (
		set /a DDay=%DDay%-73
		set /a DMonth=%DMonth%+1
	)
	if %DDay% GTR 73 (
		set /a DDay=%DDay%-73
		set /a DMonth=%DMonth%+1
	)
	if %DDay% GTR 73 (
		set /a DDay=%DDay%-73
		set /a DMonth=%DMonth%+1
	)
	if %DDay% GTR 73 (
		set /a DDay=%DDay%-73
		set /a DMonth=%DMonth%+1
	)
goto DDay

:DDay
	if %GLeap% EQU 1 (
		if %GDayThisYear% GEQ 61 (
			set /a DDay=%DDay%-1
		)
	)
	if %DDay% EQU 0 (
		set /a DDay=73
		set /a DMonth=%DMonth%-1
	)
goto DMonthName

:DMonthName
	if %DMonth% EQU 1 set DMonthName=Chaos
	if %DMonth% EQU 2 set DMonthName=Discord
	if %DMonth% EQU 3 set DMonthName=Confusion
	if %DMonth% EQU 4 set DMonthName=Bureaucracy
	if %DMonth% EQU 5 set DMonthName=Aftermath
goto DTib

:DTib
	set DTib=0
	if %GDayThisYear% EQU 60 if %GLeap% EQU 1 set DTib=1
	if %GLeap% EQU 1 if %GDayThisYear% GTR 60 set /a GDayThisYear=%GDayThisYear%-1
	set DWeekday=%GDayThisYear%
goto DWeekday

:DWeekday
	if %DWeekday% LEQ 5 goto _DWeekday
	set /a DWeekday=%DWeekday%-5
	goto DWeekday
:_DWeekday
	if %DWeekday% EQU 1 set DWeekday=Sweetmorn
	if %DWeekday% EQU 2 set DWeekday=Boomtime
	if %DWeekday% EQU 3 set DWeekday=Pungenday
	if %DWeekday% EQU 4 set DWeekday=Prickle-Prickle
	if %DWeekday% EQU 5 set DWeekday=Setting Orange
goto GWeekday

:GWeekday
goto GEnding

:GEnding
	set GEnding=th
	for %%a in (1 21 31) do	if %GDay% EQU %%a set GEnding=st
	for %%a in (2 22) do 	if %GDay% EQU %%a set GEnding=nd
	for %%a in (3 23) do	if %GDay% EQU %%a set GEnding=rd
goto DEnding

:DEnding
	set DEnding=th
	for %%a in (1 21 31 41 51 61 71) do if %Dday% EQU %%a set DEnding=st
	for %%a in (2 22 32 42 52 62 72) do if %Dday% EQU %%a set DEnding=nd
	for %%a in (3 23 33 43 53 63 73) do if %Dday% EQU %%a set DEnding=rd
goto Display

:Display
	if "%Verbose%"=="1" goto Display2
	echo.
	if %DTib% EQU 1 (
		echo St. Tib's Day, %DYear%
	) else echo %DWeekday%, %DMonthName% %DDay%%DEnding%, %DYear%
goto Epilogue

:Display2
	echo.
	echo  Gregorian: %GMonthName% %GDay%%GEnding%, %GYear%
	if %DTib% EQU 1 (
		echo Discordian: St. Tib's Day, %DYear%
	) else echo Discordian: %DWeekday%, %DMonthName% %DDay%%DEnding%, %DYear%
goto Epilogue

:Epilogue
set Verbose=
set dateToTest=
echo.

:End
Output:
H:\>ddate

Pungenday, Confusion 12th, 3182

H:\>ddate /v

 Gregorian: June 07th, 2016
Discordian: Pungenday, Confusion 12th, 3182

H:\>ddate /d 2016-02-28

Prickle-Prickle, Chaos 59th, 3182

H:\>ddate /v /d 2016-02-28

 Gregorian: February 28th, 2016
Discordian: Prickle-Prickle, Chaos 59th, 3182

H:\>ddate /v /d 2016-02-29

 Gregorian: February 29th, 2016
Discordian: St. Tib's Day, 3182

H:\>ddate /d 2016-02-29

St. Tib's Day, 3182

H:\>

This program assumes the date is in ISO order (yyyy-mm-dd) and has leading zeros. It also assumes the system date is similarly formatted, which is atypical on Windows machines.

Built on CMD.EXE version 5.1.2600.5512 (xpsp.080413-2111).

BBC BASIC

      INSTALL @lib$+"DATELIB"
      
      PRINT "01/01/2011 -> " FNdiscordian("01/01/2011")
      PRINT "05/01/2011 -> " FNdiscordian("05/01/2011")
      PRINT "28/02/2011 -> " FNdiscordian("28/02/2011")
      PRINT "01/03/2011 -> " FNdiscordian("01/03/2011")
      PRINT "22/07/2011 -> " FNdiscordian("22/07/2011")
      PRINT "31/12/2011 -> " FNdiscordian("31/12/2011")
      
      PRINT "01/01/2012 -> " FNdiscordian("01/01/2012")
      PRINT "05/01/2012 -> " FNdiscordian("05/01/2012")
      PRINT "28/02/2012 -> " FNdiscordian("28/02/2012")
      PRINT "29/02/2012 -> " FNdiscordian("29/02/2012")
      PRINT "01/03/2012 -> " FNdiscordian("01/03/2012")
      PRINT "22/07/2012 -> " FNdiscordian("22/07/2012")
      PRINT "31/12/2012 -> " FNdiscordian("31/12/2012")
      END
      
      DEF FNdiscordian(date$)
      LOCAL Season$(), Weekday$(), mjd%, year%, day%
      DIM Season$(4), Weekday$(4)
      Season$() =  "Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"
      Weekday$() = "Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange"
      
      mjd% = FN_readdate(date$, "dmy", 2000)
      year% = FN_year(mjd%)
      
      IF FN_month(mjd%)=2 AND FN_day(mjd%)=29 THEN
        = "St. Tib's Day, YOLD " + STR$(year% + 1166)
      ENDIF
      
      IF FN_month(mjd%) < 3 THEN
        day% = mjd% - FN_mjd(1, 1, year%)
      ELSE
        day% = mjd% - FN_mjd(1, 3, year%) + 59
      ENDIF
      = Weekday$(day% MOD 5) + ", " + STR$(day% MOD 73 + 1) + " " + \
      \ Season$(day% DIV 73) + ", YOLD " + STR$(year% + 1166)
Output:
01/01/2011 -> Sweetmorn, 1 Chaos, YOLD 3177
05/01/2011 -> Setting Orange, 5 Chaos, YOLD 3177
28/02/2011 -> Prickle-Prickle, 59 Chaos, YOLD 3177
01/03/2011 -> Setting Orange, 60 Chaos, YOLD 3177
22/07/2011 -> Pungenday, 57 Confusion, YOLD 3177
31/12/2011 -> Setting Orange, 73 The Aftermath, YOLD 3177
01/01/2012 -> Sweetmorn, 1 Chaos, YOLD 3178
05/01/2012 -> Setting Orange, 5 Chaos, YOLD 3178
28/02/2012 -> Prickle-Prickle, 59 Chaos, YOLD 3178
29/02/2012 -> St. Tib's Day, YOLD 3178
01/03/2012 -> Setting Orange, 60 Chaos, YOLD 3178
22/07/2012 -> Pungenday, 57 Confusion, YOLD 3178
31/12/2012 -> Setting Orange, 73 The Aftermath, YOLD 3178

Befunge

Reads the date to convert from stdin as three separate numeric inputs (year, month, and day).

0" :raeY">:#,_&>\" :htnoM">:#,_&>04p" :yaD">:#,_$&>55+,1-:47*v
v"f I".+1%,,,,"Day I":$_:#<0#!4#:p#-4#1g4-#0+#<<_v#!*!-2g40!-<
>"o",,,/:5+*66++:4>g#<:#44#:9#+*#1-#,_$$0 v_v#!< >$ 0 "yaD " v
@,+55.+*+92"j"$_,#!>#:<", in the YOLD"*84 <.>,:^ :"St. Tib's"<
$# #"#"##"#"Chaos$Discord$Confusion$Bureaucracy$The Aftermath$
Output:
(multiple runs)
Year: 2015
Month: 10
Day: 19

Day 73 of Bureaucracy, in the YOLD 3181

Year: 2012
Month: 2
Day: 29

St. Tib's Day, in the YOLD 3178

Year: 2010
Month: 7
Day: 22

Day 57 of Confusion, in the YOLD 3176

C

For the source code of ddate in util-linux package, see [[1]].

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
 
#define day_of_week( x ) ((x) == 1 ? "Sweetmorn" :\
                          (x) == 2 ? "Boomtime" :\
                          (x) == 3 ? "Pungenday" :\
                          (x) == 4 ? "Prickle-Prickle" :\
                          "Setting Orange")
 
#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, %s %d, YOLD %d",
           day_of_week(d%5), season(((d%73)==0?d-1: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 ] ) );
  }
 
  char * result = ddate( year, doy );
  puts( result );
  free( result );
 
  return 0;
}

Demonstration:

$ ./ddate 2015 10 19
Boomtime, Bureaucracy 73, YOLD 3181
$ ./ddate 7 1 2011
Sweetmorn, The Aftermath 40, YOLD 1173
$ ./ddate 2011 1 7
Boomtime, Chaos 7, YOLD 3177
$ ./ddate 2012 2 28
Prickle-Prickle, Chaos 59, YOLD 3178
$ ./ddate 2012 2 29
St. Tib's Day, YOLD 3178
$ ./ddate 2012 3 1
Setting Orange, Chaos 60, YOLD 3178
$ ./ddate 2010 7 22
Pungenday, Confusion 57, YOLD 3176
$ ./ddate # today is Jan 4, 2016
Prickle-Prickle, Chaos 4, YOLD 3182

C#

using System;

public static class DiscordianDate
{
    static readonly string[] seasons = { "Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath" };
    static readonly string[] weekdays = { "Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange" };
    static readonly string[] apostles = { "Mungday", "Mojoday", "Syaday", "Zaraday", "Maladay" };
    static readonly string[] holidays = { "Chaoflux", "Discoflux", "Confuflux", "Bureflux", "Afflux" };
    
    public static string Discordian(this DateTime date) {
        string yold = $" in the YOLD {date.Year + 1166}.";
        int dayOfYear = date.DayOfYear;

        if (DateTime.IsLeapYear(date.Year)) {
            if (dayOfYear == 60) return "St. Tib's day" + yold;
            else if (dayOfYear > 60) dayOfYear--;
        }
        dayOfYear--;

        int seasonDay = dayOfYear % 73 + 1;
        int seasonNr = dayOfYear / 73;
        int weekdayNr = dayOfYear % 5;
        string holyday = "";

        if (seasonDay == 5)       holyday = $" Celebrate {apostles[seasonNr]}!";
        else if (seasonDay == 50) holyday = $" Celebrate {holidays[seasonNr]}!";
        return $"{weekdays[weekdayNr]}, day {seasonDay} of {seasons[seasonNr]}{yold}{holyday}";
    }

    public static void Main() {
        foreach (var (day, month, year) in new [] {
            (1, 1, 2010),
            (5, 1, 2010),
            (19, 2, 2011),
            (28, 2, 2012),
            (29, 2, 2012),
            (1, 3, 2012),
            (19, 3, 2013),
            (3, 5, 2014),
            (31, 5, 2015),
            (22, 6, 2016),
            (15, 7, 2016),
            (12, 8, 2017),
            (19, 9, 2018),
            (26, 9, 2018),
            (24, 10, 2019),
            (8, 12, 2020),
            (31, 12, 2020)
        })
        {
            Console.WriteLine($"{day:00}-{month:00}-{year:00} = {new DateTime(year, month, day).Discordian()}");
        }
    }

}
Output:
01-01-2010 = Sweetmorn, day 1 of Chaos in the YOLD 3176.
05-01-2010 = Setting Orange, day 5 of Chaos in the YOLD 3176. Celebrate Mungday!
19-02-2011 = Setting Orange, day 50 of Chaos in the YOLD 3177. Celebrate Chaoflux!
28-02-2012 = Prickle-Prickle, day 59 of Chaos in the YOLD 3178.
29-02-2012 = St. Tib's day in the YOLD 3178.
01-03-2012 = Setting Orange, day 60 of Chaos in the YOLD 3178.
19-03-2013 = Pungenday, day 5 of Discord in the YOLD 3179. Celebrate Mojoday!
03-05-2014 = Pungenday, day 50 of Discord in the YOLD 3180. Celebrate Discoflux!
31-05-2015 = Sweetmorn, day 5 of Confusion in the YOLD 3181. Celebrate Syaday!
22-06-2016 = Pungenday, day 27 of Confusion in the YOLD 3182.
15-07-2016 = Sweetmorn, day 50 of Confusion in the YOLD 3182. Celebrate Confuflux!
12-08-2017 = Prickle-Prickle, day 5 of Bureaucracy in the YOLD 3183. Celebrate Zaraday!
19-09-2018 = Boomtime, day 43 of Bureaucracy in the YOLD 3184.
26-09-2018 = Prickle-Prickle, day 50 of Bureaucracy in the YOLD 3184. Celebrate Bureflux!
24-10-2019 = Boomtime, day 5 of The Aftermath in the YOLD 3185. Celebrate Maladay!
08-12-2020 = Boomtime, day 50 of The Aftermath in the YOLD 3186. Celebrate Afflux!
31-12-2020 = Setting Orange, day 73 of The Aftermath in the YOLD 3186.

C++

#include <iostream>
#include <algorithm>
#include <vector>
#include <sstream>
#include <iterator>
using namespace std;
class myTuple
{
public:
    void set( int a, int b, string c ) { t.first.first = a; t.first.second = b; t.second = c; }
    bool operator == ( pair<int, int> p ) { return p.first == t.first.first && p.second == t.first.second; }
    string second() { return t.second; }
private:
    pair<pair<int, int>, string> t;
};
class discordian
{
public:
    discordian() {
        myTuple t;
        t.set( 5, 1, "Mungday" ); holyday.push_back( t ); t.set( 19, 2, "Chaoflux" ); holyday.push_back( t );
        t.set( 29, 2, "St. Tib's Day" ); holyday.push_back( t ); t.set( 19, 3, "Mojoday" ); holyday.push_back( t );
        t.set( 3, 5, "Discoflux" ); holyday.push_back( t ); t.set( 31, 5, "Syaday" ); holyday.push_back( t );
        t.set( 15, 7, "Confuflux" ); holyday.push_back( t ); t.set( 12, 8, "Zaraday" ); holyday.push_back( t ); 
        t.set( 26, 9, "Bureflux" ); holyday.push_back( t ); t.set( 24, 10, "Maladay" ); holyday.push_back( t ); 
        t.set( 8, 12, "Afflux" ); holyday.push_back( t ); 
        seasons.push_back( "Chaos" ); seasons.push_back( "Discord" ); seasons.push_back( "Confusion" ); 
        seasons.push_back( "Bureaucracy" ); seasons.push_back( "The Aftermath" );
        wdays.push_back( "Setting Orange" ); wdays.push_back( "Sweetmorn" ); wdays.push_back( "Boomtime" );
        wdays.push_back( "Pungenday" ); wdays.push_back( "Prickle-Prickle" ); 
    }
    void convert( int d, int m, int y ) {
        if( d == 0 || m == 0 || m > 12 || d > getMaxDay( m, y ) ) { 
            cout << "\nThis is not a date!"; 
            return; 
        }
        vector<myTuple>::iterator f = find( holyday.begin(), holyday.end(), make_pair( d, m ) ); 
        int dd = d, day, wday, sea,  yr = y + 1166;
        for( int x = 1; x < m; x++ )
            dd += getMaxDay( x, 1 );
        day = dd % 73; if( !day ) day = 73; 
        wday = dd % 5; 
        sea  = ( dd - 1 ) / 73;
        if( d == 29 && m == 2 && isLeap( y ) ) { 
            cout << ( *f ).second() << " " << seasons[sea] << ", Year of Our Lady of Discord " << yr; 
            return; 
        }
        cout << wdays[wday] << " " << seasons[sea] << " " << day;
        if( day > 10 && day < 14 ) cout << "th"; 
        else switch( day % 10) { 
            case 1: cout << "st"; break; 
            case 2: cout << "nd"; break; 
            case 3: cout << "rd"; break; 
            default: cout << "th"; 
        }
        cout << ", Year of Our Lady of Discord " << yr;
        if( f != holyday.end() ) cout << " - " << ( *f ).second();
    }
private:
    int getMaxDay( int m, int y ) { 
        int dd[] = { 0, 31, isLeap( y ) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; return dd[m]; 
    }
    bool isLeap( int y ) { 
        bool l = false; 
        if( !( y % 4 ) ) { 
            if( y % 100 ) l = true; 
            else if( !( y % 400 ) ) l = true; 
        }
        return l; 
    }
    vector<myTuple> holyday; vector<string> seasons, wdays;
};
int main( int argc, char* argv[] ) {
    string date; discordian disc;
    while( true ) {
        cout << "Enter a date (dd mm yyyy) or 0 to quit: "; getline( cin, date ); if( date == "0" ) break;
        if( date.length() == 10 ) {
            istringstream iss( date ); 
            vector<string> vc;
            copy( istream_iterator<string>( iss ), istream_iterator<string>(), back_inserter<vector<string> >( vc ) );
            disc.convert( atoi( vc[0].c_str() ), atoi( vc[1].c_str() ), atoi( vc[2].c_str() ) ); 
            cout << "\n\n\n";
        } else cout << "\nIs this a date?!\n\n";
    }
    return 0;
}
Output:

Enter a date (dd mm yyyy) or 0 to quit: 19 10 2015 Boomtime, Bureaucracy 73rd, Year of Our Lady of Discord 3181

Enter a date (dd mm yyyy) or 0 to quit: 08 06 2015 Prickle-Prickle, Confusion 13th, Year of Our Lady of Discord 3181

Enter a date (dd mm yyyy) or 0 to quit: 23 06 2015 Prickle-Prickle, Confusion 28th, Year of Our Lady of Discord 3181

Enter a date (dd mm yyyy) or 0 to quit: 29 02 2016 St. Tib's Day, Year of Our Lady of Discord 3182

Enter a date (dd mm yyyy) or 0 to quit: 05 01 2016 Setting Orange, Chaos 5th, Year of Our Lady of Discord 3182 - Mungday

Enter a date (dd mm yyyy) or 0 to quit: 26 08 2016 Pungenday, Bureaucracy 19th, Year of Our Lady of Discord 3182

Clojure

(require '[clj-time.core :as tc])

(def seasons ["Chaos" "Discord" "Confusion" "Bureaucracy" "The Aftermath"])
(def weekdays ["Sweetmorn" "Boomtime" "Pungenday" "Prickle-Prickle" "Setting Orange"])
(def year-offset 1166)

(defn leap-year? [year]
  (= 29 (tc/number-of-days-in-the-month year 2)))

(defn discordian-day [day leap]
  (let [offset (if (and leap (>= day 59)) 1 0)
        day-off (- day offset)
        day-num (inc (rem day-off 73))
        season (seasons (quot day-off 73))
        weekday (weekdays (mod day-off 5))]
    (if (and (= day 59) (= offset 1))
      "St. Tib's Day"
      (str weekday ", " season " " day-num))))

(defn discordian-date [year month day]
  (let [day-of-year (dec (.getDayOfYear (tc/date-time year month day)))
        dday (discordian-day day-of-year (leap-year? year))]
    (format "%s, YOLD %s" dday (+ year year-offset))))
Output:
user=> (discordian-date 2010 7 22)
"Pungenday, Confusion 57, YOLD 3176"
user=> (discordian-date 2012 2 28)
"Prickle-Prickle, Chaos 59, YOLD 3178"
user=> (discordian-date 2012 2 29)
"St. Tib's Day, YOLD 3178"
user=> (discordian-date 2012 3 1)
"Setting Orange, Chaos 60, YOLD 3178"
user=> (discordian-date 2012 12 31)
"Setting Orange, The Aftermath 73, YOLD 3178"
user=> (discordian-date 2013 12 31)
"Setting Orange, The Aftermath 73, YOLD 3179"

CLU

% This program needs to be merged with PCLU's "useful.lib",
% so it can use get_argv to read the command line. 
%
% pclu -merge $CLUHOME/lib/useful.lib -compile cmdline.clu

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Represent a day in the Discordian calendar %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
eris_date = cluster is from_greg_y_m_d,
                       from_date,
                       get_year,
                       get_day,
                       get_season,
                       get_weekday,
                       get_day_name,
                       get_holyday,
                       get_format
    greyface = 1166 
    
    % A Discordian day is either St. Tib's day
    % or a day in a season
    season_day = struct[season, day: int] 
    eris_day = oneof[st_tibs: null, season_day: season_day]
    
    % A Discordian date is a day in a year
    rep = struct[year: int, day: eris_day]
    
    % Offset of each Gregorian month in a non-leap year
    own month_offset: sequence[int] := sequence[int]$[
        0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
    ]
    
    % Length of each Gregorian month in a non-leap year
    own month_length: sequence[int] := sequence[int]$[
        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    ]
    
    own week_days: sequence[string] := sequence[string]$[
        "Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle",
        "Setting Orange"
    ]
    
    own seasons: sequence[string] := sequence[string]$[
        "Chaos", "Discord", "Confusion", "Bureacuracy",
        "The Aftermath"
    ]
    
    own apostle_holydays: sequence[string] := sequence[string]$[
        "Mungday", "Mojoday", "Syaday", "Zaraday", "Maladay"
    ]
    
    own season_holydays: sequence[string] := sequence[string]$[
        "Chaoflux", "Discoflux", "Confuflux", "Bureflux", "Afflux"
    ]
    
    % Check if a Gregorian year is a leap year
    is_leap = proc (year: int) returns (bool)
        if year // 4 ~= 0 then return(false)
        elseif year // 100 ~= 0 then return(true)
        elseif year // 400 ~= 0 then return(false)
        else return(true)
        end
    end is_leap
        
    % Convert a Gregorian date to a Discordian date
    from_greg_y_m_d = proc (year, month, day: int) 
                      returns (cvt) signals (invalid)
        % Make sure the month is valid
        if month<1 cor month>12 then signal invalid end
        
        % Saint Tib's Day?
        if month=2 cand day=29 then
            % Only valid in leap years
            if ~is_leap(year) then signal invalid end
            return(rep${year: year+greyface, day: eris_day$make_st_tibs(nil)})
        end
        
        % If not, make sure the day of the month is valid
        if day<1 cor day>month_length[month] then signal invalid end
        
        % The Discordian calendar doesn't consider Saint Tib's Day 
        % part of a season, so we can use the day number for a non-leap 
        % year even in a leap year
        year_day: int := (day + month_offset[month]) - 1
        sd: season_day := season_day${
            season: year_day / 73 + 1,
            day: year_day // 73 + 1
        }
        return(rep${year: year+greyface,
                    day: eris_day$make_season_day(sd)})
    end from_greg_y_m_d
    
    % Convert a CLU 'date' object to a Discordian date (ignoring the time)
    from_date = proc (d: date) returns (cvt) signals (invalid)
        return(down(from_greg_y_m_d(d.year, d.month, d.day)))
        resignal invalid
    end from_date
    
    % Retrieve year, season, day, weekday number
    get_year = proc (d: cvt) returns (int) return(d.year) end get_year
    
    get_day = proc (d: cvt) returns (int) signals (st_tibs)
        tagcase d.day
            tag st_tibs: signal st_tibs
            tag season_day (s: season_day): return(s.day)
        end
    end get_day
    
    get_season = proc (d: cvt) returns (int) signals (st_tibs)
        tagcase d.day
            tag st_tibs: signal st_tibs
            tag season_day (s: season_day): return(s.season)
        end
    end get_season
    
    get_weekday = proc (d: cvt) returns (int) signals (st_tibs)
        day: int := up(d).day resignal st_tibs
        season: int := up(d).season resignal st_tibs
        weekday: int := ( (season-1)*73 + (day-1) ) // 5 + 1
        return( weekday )
    end get_weekday
    
    % Retrieve formatted day in year
    get_day_name = proc (d: cvt) returns (string)
        begin
            fmt: stream := stream$create_output()
            stream$puts(fmt, week_days[up(d).weekday])
            stream$puts(fmt, ", day " || int$unparse(up(d).day))
            stream$puts(fmt, " of " || seasons[up(d).season])
            return(stream$get_contents(fmt))
        end except when st_tibs:
            return("St. Tib's Day")
        end
    end get_day_name
    
    % Retrieve holyday name if there is one
    get_holyday = proc (d: cvt) returns (string) signals (no_holyday)
        begin
            if up(d).day = 5 then return(apostle_holydays[up(d).season])
            elseif up(d).day = 50 then return(season_holydays[up(d).season])
            else signal no_holyday
            end
        end except when st_tibs:
            signal no_holyday  % St. Tib's Day is not a normal holyday
        end
    end get_holyday
    
    % Retrieve long format
    get_format = proc (d: cvt) returns (string)
        fmt: stream := stream$create_output()
        stream$puts(fmt, up(d).day_name)
        stream$puts(fmt, " in the YOLD ")
        stream$puts(fmt, int$unparse(up(d).year))
        stream$puts(fmt, ": celebrate " || up(d).holyday) except when no_holyday: end
        return(stream$get_contents(fmt))
    end get_format
end eris_date

% Parse a date string (MM/DD/YYYY) and return a date object
parse_date = proc (s: string) returns (date) signals (bad_format)
    begin
        parts: array[int] := array[int]$[]
        while true do
            slash: int := string$indexc('/', s)
            if slash=0 then 
                array[int]$addh(parts, int$parse(s))
                break
            else
                array[int]$addh(parts, int$parse(string$substr(s, 1, slash-1)))
                s := string$rest(s, slash+1)
            end
        end
        if array[int]$size(parts) ~= 3 then signal bad_format end
        return(date$create(parts[2], parts[1], parts[3], 0, 0, 0))
    end resignal bad_format
end parse_date

% Read date(s) from the command line, or use the current date,
% and convert to the Discordian date
start_up = proc ()
    po: stream := stream$primary_output()
    args: sequence[string] := get_argv()
    dates: array[date] := array[date]$[]
    
    if sequence[string]$empty(args) then 
        % No argument - use today's date 
        stream$puts(po, "Today is ")
        array[date]$addh(dates, now())
    else 
        % There are argument(s) - parse each of them
        for arg: string in sequence[string]$elements(args) do
            array[date]$addh(dates, parse_date(arg))
        end
    end
    
    % Convert all dates
    for d: date in array[date]$elements(dates) do
        stream$putl(po, eris_date$from_date(d).format)
    end
end start_up
Output:
$ ./ddate
Today is Boomtime, day 45 of The Aftermath in the YOLD 3187

$ ./ddate 4/27/2020 9/26/1995 2/29/1996 7/22/2011 1/5/2005
Boomtime, day 44 of Discord in the YOLD 3186
Prickle-Prickle, day 50 of Bureacuracy in the YOLD 3161: celebrate Bureflux
St. Tib's Day in the YOLD 3162
Pungenday, day 57 of Confusion in the YOLD 3177
Setting Orange, day 5 of Chaos in the YOLD 3171: celebrate Mungday

D

import std.stdio, std.datetime, std.conv, std.string;
 
immutable seasons = ["Chaos", "Discord", "Confusion",
                     "Bureaucracy", "The Aftermath"],
          weekday = ["Sweetmorn", "Boomtime", "Pungenday",
                     "Prickle-Prickle", "Setting Orange"],
          apostle = ["Mungday", "Mojoday", "Syaday",
                     "Zaraday", "Maladay"],
          holiday = ["Chaoflux", "Discoflux", "Confuflux",
                     "Bureflux", "Afflux"];
 
string discordianDate(in Date date) pure {
    immutable dYear = text(date.year + 1166);
 
    immutable isLeapYear = date.isLeapYear;
    if (isLeapYear && date.month == 2 && date.day == 29)
        return "St. Tib's Day, in the YOLD " ~ dYear;
 
    immutable doy = (isLeapYear && date.dayOfYear >= 60) ?
                    date.dayOfYear - 1 :
                    date.dayOfYear;
 
    immutable dsDay = (doy % 73)==0? 73:(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;
 
    immutable dSeas = seasons[(((doy%73)==0)?doy-1:doy) / 73];
    immutable dWday = weekday[(doy - 1) % 5];
 
    return format("%s, day %s of %s in the YOLD %s",
                  dWday, dsDay, dSeas, dYear);
}
 
unittest {
    assert(Date(2010, 7, 22).discordianDate ==
           "Pungenday, day 57 of Confusion in the YOLD 3176");
    assert(Date(2012, 2, 28).discordianDate ==
           "Prickle-Prickle, day 59 of Chaos in the YOLD 3178");
    assert(Date(2012, 2, 29).discordianDate ==
           "St. Tib's Day, in the YOLD 3178");
    assert(Date(2012, 3, 1).discordianDate ==
           "Setting Orange, day 60 of Chaos in the YOLD 3178");
    assert(Date(2010, 1, 5).discordianDate ==
           "Mungday, in the YOLD 3176");
    assert(Date(2011, 5, 3).discordianDate ==
           "Discoflux, in the YOLD 3177");
}
 
void main(string args[]) {
    int yyyymmdd, day, mon, year, sign;
    if (args.length == 1) {
       (cast(Date)Clock.currTime).discordianDate.writeln;
       return;
    }
    foreach (i, arg; args) {
        if (i > 0) {
            //writef("%d: %s: ", i, arg);
            yyyymmdd = to!int(arg);
            if (yyyymmdd < 0) {
                sign = -1;
                yyyymmdd = -yyyymmdd;
            }
            else {
                sign = 1;
            }
            day = yyyymmdd % 100;
            if (day == 0) {
               day = 1;
            }
            mon = ((yyyymmdd - day) / 100) % 100;
            if (mon == 0) {
               mon = 1;
            }
            year = sign * ((yyyymmdd - day - 100*mon) / 10000);
            writefln("%s", Date(year, mon, day).discordianDate);
        }
    } 
}
Output:
$ ./ddate 20100722 20120228 20120229 20120301 20100105 20110503 20151019 00000101 -11660101
Pungenday, day 57 of Confusion in the YOLD 3176
Prickle-Prickle, day 59 of Chaos in the YOLD 3178
St. Tib's Day, in the YOLD 3178
Setting Orange, day 60 of Chaos in the YOLD 3178
Mungday, in the YOLD 3176
Discoflux, in the YOLD 3177
Boomtime, day 73 of Bureaucracy in the YOLD 3181
Sweetmorn, day 1 of Chaos in the YOLD 1166
Sweetmorn, day 1 of Chaos in the YOLD 0

Delphi

Translation of: D
Partial translation of D.
program Discordian_date;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.DateUtils;

type
  TDateTimeHelper = record helper for TDateTime
    const
      seasons: array of string = ['Chaos', 'Discord', 'Confusion', 'Bureaucracy',
        'The Aftermath'];
      weekday: array of string = ['Sweetmorn', 'Boomtime', 'Pungenday',
        'Prickle-Prickle', 'Setting Orange'];
      apostle: array of string = ['Mungday', 'Mojoday', 'Syaday', 'Zaraday', 'Maladay'];
      holiday: array of string = ['Chaoflux', 'Discoflux', 'Confuflux',
        'Bureflux', 'Afflux'];
    function DiscordianDate(): string;
  end;

{ TDateTimeHelper }

function TDateTimeHelper.DiscordianDate: string;
var
  isLeapYear: boolean;
begin
  isLeapYear := IsInLeapYear(self);
  var dYear := (YearOf(self) + 1166).ToString;
  if isLeapYear and (MonthOf(self) = 2) and (dayof(self) = 29) then
    exit('St. Tib''s Day, in the YOLD ' + dYear);

  var doy := DayOfTheYear(self);
  if isLeapYear and (doy >= 60) then
    doy := doy - 1;

  var dsDay := doy mod 73;

  if dsDay = 0 then
    dsDay := 73;

  if dsDay = 5 then
    exit(apostle[doy div 73] + ', in the YOLD ' + dYear);

  if dsDay = 50 then
    exit(holiday[doy div 73] + ', in the YOLD ' + dYear);

  var dSeas: string;

  if (doy mod 73) = 0 then
    dSeas := seasons[(doy - 1) div 73]
  else
    dSeas := seasons[doy div 73];

  var dWday := weekday[(doy - 1) mod 5];

  Result := format('%s, day %d of %s in the YOLD %s', [dWday, dsDay, dSeas, dYear]);

end;

procedure Test();
begin
  Assert(EncodeDate(2010, 7, 22).DiscordianDate =
    'Pungenday, day 57 of Confusion in the YOLD 3176');
  Assert(EncodeDate(2012, 2, 28).DiscordianDate =
    'Prickle-Prickle, day 59 of Chaos in the YOLD 3178');
  Assert(EncodeDate(2012, 2, 29).DiscordianDate = 'St. Tib''s Day, in the YOLD 3178');
  Assert(EncodeDate(2012, 3, 1).DiscordianDate =
    'Setting Orange, day 60 of Chaos in the YOLD 3178');
  Assert(EncodeDate(2010, 1, 5).DiscordianDate = 'Mungday, in the YOLD 3176');
  Assert(EncodeDate(2011, 5, 3).DiscordianDate = 'Discoflux, in the YOLD 3177');
  writeln('OK');
end;

var
  dt: TDateTime;
  i: Integer;

begin
  if ParamCount = 0 then
  begin
    writeln(now.DiscordianDate);
    readln;
    halt;
  end;

  for i := 1 to ParamCount do
  begin
    if not TryStrToDate(ParamStr(i), dt) then
      Continue;
    writeln(dt.DiscordianDate);
  end;

  readln;
end.

EasyLang

seasons$[] = [ "Chaos" "Discord" "Confusion" "Bureaucracy" "The Aftermath" ]
weekday$[] = [ "Sweetmorn" "Boomtime" "Pungenday" "Prickle-Prickle" "Setting Orange" ]
apostle$[] = [ "Mungday" "Mojoday" "Syaday" "Zaraday" "Maladay" ]
holiday$[] = [ "Chaoflux" "Discoflux" "Confuflux" "Bureflux" "Afflux" ]
# 
func leap x .
   return if x mod 400 = 0 or x mod 4 = 0 and x mod 100 <> 0
.
func day_of_year y m d .
   days[] = [ 31 28 31 30 31 30 31 31 30 31 30 31 ]
   repeat
      m -= 1
      until m = 0
      d += days[m]
      if m = 2 and leap y = 1
         d += 1
      .
   .
   return d
.
func$ ddate y m d .
   doy = day_of_year y m d
   dyear = y + 1166
   if leap y = 1 and m = 2 and d = 29
      return "St. Tib's Day, in the YOLD " & dyear
   .
   if leap y = 1 and doy >= 60
      doy -= 1
   .
   dsday = doy mod1 73
   dseason = doy div1 73
   r$ = weekday$[doy mod1 5] & ", day " & dsday & " of " & seasons$[dseason]
   r$ &= " in the YOLD " & dyear & "."
   if dsday = 5
      r$ &= " Celebrate " & apostle$[dseason] & "!"
   elif dsday = 50
      r$ &= " Celebrate " & holiday$[dseason] & "!"
   .
   return r$
.
proc show d$ . .
   a[] = number strsplit d$ "-"
   write d$ & " --> "
   print ddate a[1] a[2] a[3]
.
show "2016-01-05"
show "2016-02-28"
show "2016-02-29"
show "2016-03-01"
show "2016-12-31"
show "2025-03-19"
show substr timestr systime 1 10

Euphoria

Translation of: D
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))

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) - 1
        let season, dday = Math.DivRem(dayOfYear, 73)
        sprintf "%s %i, %i YOLD" seasons.[season] (dday+1) dyear

[<EntryPoint>]
let main argv = 
    let p = Int32.Parse
    Seq.ofArray("2012-02-28 2012-02-29 2012-03-01 2010-07-22 2015-10-19 2015-10-20".Split())
    |> Seq.map(fun (s:string) ->
        let d = s.Split('-')
        (s, DateTime(p(d.[0]),p(d.[1]),p(d.[2]))))
    |> Seq.iter(fun (s,d) -> printfn "%s is %s" s (ddate d))
    0
Output:
2012-02-28 is Chaos 59, 3178 YOLD
2012-02-29 is St. Tib's Day, 3178 YOLD
2012-03-01 is Chaos 60, 3178 YOLD
2010-07-22 is Confusion 57, 3176 YOLD
2015-10-19 is Bureaucracy 73, 3181 YOLD
2015-10-20 is The Aftermath 1, 3181 YOLD

Fortran

program discordianDate
    implicit none
    ! Declare variables
    character(32) :: arg
    character(15) :: season,day,holyday
    character(80) :: Output,fmt1,fmt2,fmt3
    character(2) :: dayfix,f1,f2,f3,f4
    integer :: i,j,k,daysofyear,dayofweek,seasonnum,yold,dayofseason,t1,t2,t3
    integer,dimension(8) :: values
    integer, dimension(12) :: daysinmonth
    logical  :: isleapyear, isholyday, Pleapyear
     
    ! Get the current date
    call date_and_time(VALUES=values)
    ! Set some values up to defaults
    daysinmonth = (/ 31,28,31,30,31,30,31,31,30,31,30,31 /)
    isleapyear = .false.
    isholyday = .false.
    ! process any command line arguments
    ! using arguments dd mm yyyy 
    j = iargc()
    do i = 1, iargc()
      call getarg(i, arg)  ! fetches argument as a character string
      if (j==3) then
        if (i==1) then
          read(arg,'(i2)') values(3)  ! convert to integer
        endif
        if (i==2) then
          read(arg,'(i2)') values(2)  ! convert to integer
        endif
        if (i==3) then
          read(arg,'(i4)') values(1)  ! convert to integer
 
        endif
      endif
      if (j==2) then  ! arguments dd mm
        if (i==1) then
          read(arg,'(i2)') values(3)  ! convert to integer
        endif
        if (i==2) then
          read(arg,'(i2)') values(2)  ! convert to integer
        endif
      endif
      if (j==1) then ! argument dd
        read(arg,'(i2)') values(3)  ! convert to integer
      endif
    end do
 
    !Start the number crunching here 

    yold = values(1) + 1166
    daysofyear = 0
    if (values(2)>1) then 
    do i=1 , values(2)-1 , 1
        daysofyear = daysofyear + daysinmonth(i)
     end do
   end if
    daysofyear = daysofyear + values(3)
    isholyday = .false.
    isleapyear = Pleapyear(yold)
    dayofweek = mod (daysofyear, 5)
    seasonnum = ((daysofyear - 1) / 73) + 1 
    dayofseason = daysofyear - ((seasonnum - 1)  * 73)
    k = mod(dayofseason,10)  ! just to get the day number postfix
    select case (k)
      case (1)
         dayfix='st'
      case (2)
         dayfix='nd'
      case (3)
         dayfix='rd'
      case default
         dayfix='th'
    end select
    ! except between 10th and 20th  where we always have 'th'
    if (((dayofseason > 10) .and. (dayofseason < 20)) .eqv. .true.) then
      dayfix = 'th'
    end if
    select case (Seasonnum)
      case (1) 
        season ='Choas'
        f4 = '5'
      case (2) 
        season ='Discord'
        f4 = '7'
      case (3) 
        season ='Confusion'
        f4 = '9'
      case (4) 
        season ='Bureaucracy'
        f4 = '10'
      case (5) 
        season ='The Aftermath'
        f4 = '13'
    end select
    select case (dayofweek)
       case (0) 
         day='Setting Orange'
         f2 = '14'
       case (1) 
         day ='Sweetmorn'
         f2 = '9'
       case (2) 
         day = 'Boomtime'
         f2 = '8'
       case (3) 
         day = 'Pungenday'
         f2 = '9'
       case (4) 
         day = 'Prickle-Prickle'
         f2 = '15'
    end select
    ! check for holydays
    select case (dayofseason)
      case (5)
        isholyday = .true.
        select case (seasonnum)
          case (1)
             holyday ='Mungday'
             f1 = '7'
          case (2)
             holyday = 'Mojoday'
             f1 = '7'
          case (3)
            holyday = 'Syaday'
            f1 = '6'
          case (4)
             holyday = 'Zaraday'
             f1 = '7'
          case (5)
            holyday = 'Maladay'
            f1 = '7'
         end select
      Case (50)
        isholyday = .true.
        select case (seasonnum)
          case (1)
            holyday = 'Chaoflux'
            f1 = '8'
          case (2)
            holyday = 'Discoflux'
            f1 = '9'
          case (3)
            holyday = 'Confuflux'
            f1 = '9'
          case (4)
            holyday = 'Bureflux'
            f1 = '8'
          case (5)
            holyday = 'Afflux'
            f1 = '6'
         end select
    end select
    

    ! Check if it is St. Tibbs day
    if (isleapyear .eqv. .true.) then 
      if ((values(2) == 2) .and. (values(3) == 29)) then
         isholyday = .true.
      end if
    end if
    ! Construct our format strings
    f3 = "2"
    if (dayofseason < 10) then
      f3 = "1"
    end if
    fmt1 = "(a,i4)"
    fmt2 = "(A,a" // f1 // ",A,A" // f2 // ",A,I" // f3 // ",A2,A,A" // f4 // ",A,I4)"
    fmt3 = "(A,A" // f2 // ",A,I" // f3 //",A2,A,A" // f4 // ",A,I4)"
    ! print an appropriate line
    if (isholyday .eqv. .true.) then
      if (values(3) == 29) then
         print fmt1,'Celebrate for today is St. Tibbs Day in the YOLD ',yold
       else
         print fmt2, 'Today is ',holyday, ' on ',day,' the ',dayofseason,dayfix,' day of ',season,' in the YOLD ',yold 
       end if
     else   ! not a holyday
         print fmt3, 'Today is ',day,' the ',dayofseason,dayfix, ' day of ',season,' in the YOLD ',yold
     end if
    end program discordianDate

    ! Function to check to see if this is a leap year returns true or false!

    function Pleapyear(dloy) result(leaper)
    implicit none
    integer, intent(in) :: dloy
    logical :: leaper
    leaper = .false.
    if (mod((dloy-1166),4) == 0)  then
      leaper = .true.
    end if
    if (mod((dloy-1166),100) == 0) then
        leaper = .false.
        if (mod((dloy-1166),400)==0) then
           leaper = .true.
        end if
    end if 
    end function Pleapyear
compiled as ddate.
useage ./ddate
       ./ddate dd mm yyyy
Output:
./ddate
Today is Pungenday the 56th day of The Aftermath in the YOLD 3184
./ddate 29 02 2020
Celebrate for today is St. Tibbs Day in the YOLD 3186

FreeBASIC

Translation of: BASIC
#Include "datetime.bi"

meses:
Data "Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"
dias_laborales:
Data "Setting Orange", "Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle"
dias_previos_al_1er_mes:
'   ene feb mar abr may  jun  jul  ago  sep  oct  nov  dic
Data 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334

Function cJuliano(d As Double) As Integer
    'no tiene en cuenta los años bisiestos (no es necesario para ddate)
    Dim tmp As Integer, i As Integer
    Restore dias_previos_al_1er_mes
    For i = 1 To Month(d)
        Read tmp
    Next i
    Function = tmp + Day(d)
End Function

Sub cDiscordiano(Fecha As String)
    Dim As Integer dyear, dday, j, jday
    Dim As Double tempfecha = Datevalue(Fecha)
    Dim As String ddate, dseason, dweekday
    
    dyear = Year(tempfecha) + 1166
    If (2 = Month(tempfecha)) And (29 = Day(tempfecha)) Then
        ddate = "Saint Tib's Day, " & Str(dyear) & " YOLD"
    Else
        jday = cJuliano(tempfecha)
        Restore meses
        For j = 1 To ((jday - 1) \ 73) + 1
            Read dseason
        Next j
        dday = (jday Mod 73)
        If 0 = dday Then dday = 73
        Restore dias_laborales
        For j = 1 To (jday Mod 5) + 1
            Read dweekday
        Next j
        ddate = dweekday & ", " & dseason & " " & Trim(Str(dday)) & ", " & Trim(Str(dyear)) & " YOLD"
    End If
    Print Fecha & " -> " & ddate
End Sub

cDiscordiano("01/01/2020")
cDiscordiano("05/01/2020")
cDiscordiano("28/02/2020")
cDiscordiano("01/03/2020")
cDiscordiano("22/07/2020")
cDiscordiano("31/12/2020")
cDiscordiano("20/04/2022")
cDiscordiano("24/05/2020")
cDiscordiano("29/02/2020")
cDiscordiano("15/07/2019")
cDiscordiano("19/03/2025")
Sleep
Output:
01/01/2020 -> Sweetmorn, Chaos 1, 3186 YOLD
05/01/2020 -> Setting Orange, Chaos 5, 3186 YOLD
28/02/2020 -> Prickle-Prickle, Chaos 59, 3186 YOLD
01/03/2020 -> Setting Orange, Chaos 60, 3186 YOLD
22/07/2020 -> Pungenday, Confusion 57, 3186 YOLD
31/12/2020 -> Setting Orange, The Aftermath 73, 3186 YOLD
20/04/2022 -> Setting Orange, Discord 37, 3188 YOLD
24/05/2020 -> Prickle-Prickle, Discord 71, 3186 YOLD
29/02/2020 -> Saint Tib's Day, 3186 YOLD
15/07/2019 -> Sweetmorn, Confusion 50, 3185 YOLD
19/03/2025 -> Pungenday, Discord 5, 3191 YOLD


Go

A package modeled after the time package in the Go standard library

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 := time.Date(eris.Year(), 1, 1, eris.Hour(), eris.Minute(),
        eris.Second(), eris.Nanosecond(), eris.Location())
    bob := int(eris.Sub(t).Hours()) / 24
    raw := 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
}

Example program using above package

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.Now()
    case 3:
        var err 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)
}
Output:
> ddate
Pungenday, Confusion 62, 3177 YOLD

> ddate 29 2 2012
St. Tib's Day, 3178 YOLD

Haskell

import Data.Time (isLeapYear)
import Data.Time.Calendar.MonthDay (monthAndDayToDayOfYear)
import Text.Printf (printf)

type Year = Integer
type Day = Int
type Month = Int

data DDate = DDate Weekday Season Day Year
           | StTibsDay Year deriving (Eq, Ord)

data Season = Chaos
            | Discord
            | Confusion
            | Bureaucracy
            | TheAftermath
            deriving (Show, Enum, Eq, Ord, Bounded)

data Weekday = Sweetmorn
             | Boomtime
             | Pungenday
             | PricklePrickle
             | SettingOrange
             deriving (Show, Enum, Eq, Ord, Bounded)

instance Show DDate where
  show (StTibsDay y) = printf "St. Tib's Day, %d YOLD" y
  show (DDate w s d y) = printf "%s, %s %d, %d YOLD" (show w) (show s) d y

fromYMD :: (Year, Month, Day) -> DDate
fromYMD (y, m, d)
  | leap && dayOfYear == 59 = StTibsDay yold
  | leap && dayOfYear >= 60 = mkDDate $ dayOfYear - 1 
  | otherwise               = mkDDate dayOfYear
  where
    yold = y + 1166
    dayOfYear = monthAndDayToDayOfYear leap m d - 1
    leap = isLeapYear y

    mkDDate dayOfYear = DDate weekday season dayOfSeason yold
      where
        weekday = toEnum $ dayOfYear `mod` 5
        season = toEnum $ dayOfYear `div` 73
        dayOfSeason = 1 + dayOfYear `mod` 73

Examples:

test = mapM_ display dates
  where
    display d = putStr (show d ++ " -> ") >> print (fromYMD d)
    dates = [(2012,2,28)
            ,(2012,2,29)
            ,(2012,3,1)
            ,(2012,3,14)
            ,(2012,3,15)
            ,(2010,9,2)
            ,(2010,12,31)
            ,(2011,1,1)]
λ> test
(2012,2,28) -> PricklePrickle, Chaos 59, 3178 YOLD
(2012,2,29) -> St. Tib's Day, 3178 YOLD
(2012,3,1) -> SettingOrange, Chaos 60, 3178 YOLD
(2012,3,14) -> Pungenday, Chaos 73, 3178 YOLD
(2012,3,15) -> PricklePrickle, Discord 1, 3178 YOLD
(2010,9,2) -> SettingOrange, Bureaucracy 26, 3176 YOLD
(2010,12,31) -> SettingOrange, TheAftermath 73, 3176 YOLD
(2011,1,1) -> Sweetmorn, Chaos 1, 3177 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.

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

require'dates'
leap=: _1j1 * 0 -/@:= 4 100 400 |/ {.@]
bs=: ((#:{.) + 0 j. *@[ * {:@]) +.
disc=: ((1+0 73 bs[ +^:(58<]) -/@todayno@(,: 1 1,~{.)@]) ,~1166+{.@])~ leap

Example use:

   disc 2012 2 28
3178 1 59
   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
   disc 2100 12 31
3266 5 73
   disc 2015 10 19
3181 4 73
   disc 2000 3 13
3166 1 72j1

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.

Java

import java.util.Calendar;
import java.util.GregorianCalendar;

public class DiscordianDate {
    final static String[] seasons = {"Chaos", "Discord", "Confusion",
        "Bureaucracy", "The Aftermath"};

    final static String[] weekday = {"Sweetmorn", "Boomtime", "Pungenday",
        "Prickle-Prickle", "Setting Orange"};

    final static String[] apostle = {"Mungday", "Mojoday", "Syaday",
        "Zaraday", "Maladay"};

    final static String[] holiday = {"Chaoflux", "Discoflux", "Confuflux",
        "Bureflux", "Afflux"};

    public static String discordianDate(final GregorianCalendar date) {
        int y = date.get(Calendar.YEAR);
        int yold = y + 1166;
        int dayOfYear = date.get(Calendar.DAY_OF_YEAR);

        if (date.isLeapYear(y)) {
            if (dayOfYear == 60)
                return "St. Tib's Day, in the YOLD " + yold;
            else if (dayOfYear > 60)
                dayOfYear--;
        }

        dayOfYear--;

        int seasonDay = dayOfYear % 73 + 1;
        if (seasonDay == 5)
            return apostle[dayOfYear / 73] + ", in the YOLD " + yold;
        if (seasonDay == 50)
            return holiday[dayOfYear / 73] + ", in the YOLD " + yold;

        String season = seasons[dayOfYear / 73];
        String dayOfWeek = weekday[dayOfYear % 5];

        return String.format("%s, day %s of %s in the YOLD %s",
                dayOfWeek, seasonDay, season, yold);
    }

    public static void main(String[] args) {

        System.out.println(discordianDate(new GregorianCalendar()));

        test(2010, 6, 22, "Pungenday, day 57 of Confusion in the YOLD 3176");
        test(2012, 1, 28, "Prickle-Prickle, day 59 of Chaos in the YOLD 3178");
        test(2012, 1, 29, "St. Tib's Day, in the YOLD 3178");
        test(2012, 2, 1, "Setting Orange, day 60 of Chaos in the YOLD 3178");
        test(2010, 0, 5, "Mungday, in the YOLD 3176");
        test(2011, 4, 3, "Discoflux, in the YOLD 3177");
        test(2015, 9, 19, "Boomtime, day 73 of Bureaucracy in the YOLD 3181");
    }

    private static void test(int y, int m, int d, final String result) {
        assert (discordianDate(new GregorianCalendar(y, m, d)).equals(result));
    }
}
Output:
Setting Orange, day 4 of Confusion in the YOLD 3180

JavaScript

/**
 * All Hail Discordia! - this script prints Discordian date using system date.
 *
 * lang: JavaScript
 * author: jklu
 * contributors: JamesMcGuigan
 *
 * changelog:
 * - Modified to return same output syntax as unix ddate + module.exports - James McGuigan, 2/Chaos/3183
 *
 * source: https://rosettacode.org/wiki/Discordian_date#JavaScript
 */
var seasons = [
  "Chaos", "Discord", "Confusion",
  "Bureaucracy", "The Aftermath"
];
var weekday = [
  "Sweetmorn", "Boomtime", "Pungenday",
  "Prickle-Prickle", "Setting Orange"
];

var apostle = [
  "Mungday", "Mojoday", "Syaday",
  "Zaraday", "Maladay"
];

var holiday = [
  "Chaoflux", "Discoflux", "Confuflux",
  "Bureflux", "Afflux"
];


Date.prototype.isLeapYear = function() {
  var year = this.getFullYear();
  if( (year & 3) !== 0 ) { return false; }
  return ((year % 100) !== 0 || (year % 400) === 0);
};

// Get Day of Year
Date.prototype.getDOY = function() {
  var dayCount  = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
  var mn        = this.getMonth();
  var dn        = this.getDate();
  var dayOfYear = dayCount[mn] + dn;
  if( mn > 1 && this.isLeapYear() ) { dayOfYear++; }
  return dayOfYear;
};

Date.prototype.isToday = function() {
  var today = new Date();
  return this.getDate()     === today.getDate()
      && this.getMonth()    === today.getMonth()
      && this.getFullYear() === today.getFullYear()
  ;
};

function discordianDate(date) {
  if( !date ) { date = new Date(); }

  var y                = date.getFullYear();
  var yold             = y + 1166;
  var dayOfYear        = date.getDOY();
  var celebrateHoliday = null;

  if( date.isLeapYear() ) {
    if( dayOfYear == 60 ) {
      celebrateHoliday = "St. Tib's Day";
    }
    else if( dayOfYear > 60 ) {
      dayOfYear--;
    }
  }
  dayOfYear--;

  var divDay = Math.floor(dayOfYear / 73);

  var seasonDay = (dayOfYear % 73) + 1;
  if( seasonDay == 5 ) {
    celebrateHoliday = apostle[divDay];
  }
  if( seasonDay == 50 ) {
    celebrateHoliday = holiday[divDay];
  }

  var season    = seasons[divDay];
  var dayOfWeek = weekday[dayOfYear % 5];

  var nth = (seasonDay % 10 == 1) ? 'st'
          : (seasonDay % 10 == 2) ? 'nd'
          : (seasonDay % 10 == 3) ? 'rd'
                                  : 'th';

  return "" //(date.isToday() ? "Today is " : '')
         + dayOfWeek
         + ", the " + seasonDay + nth
         + " day of " + season
         + " in the YOLD " + yold
         + (celebrateHoliday ? ". Celebrate " + celebrateHoliday + "!" : '')
    ;
}

function test(y, m, d, result) {
  console.assert((discordianDate(new Date(y, m, d)) == result), [y, m, d, discordianDate(new Date(y, m, d)), result]);
}

// Only run test code if node calls this file directly
if( require.main === module ) {
  console.log(discordianDate(new Date(Date.now())));
  test(2010, 6, 22, "Pungenday, the 57th day of Confusion in the YOLD 3176");
  test(2012, 1, 28, "Prickle-Prickle, the 59th day of Chaos in the YOLD 3178");
  test(2012, 1, 29, "Setting Orange, the 60th day of Chaos in the YOLD 3178. Celebrate St. Tib's Day!");
  test(2012, 2,  1, "Setting Orange, the 60th day of Chaos in the YOLD 3178");
  test(2010, 0,  5, "Setting Orange, the 5th day of Chaos in the YOLD 3176. Celebrate Mungday!");
  test(2011, 4,  3, "Pungenday, the 50th day of Discord in the YOLD 3177. Celebrate Discoflux!");
  test(2015, 9, 19, "Boomtime, the 73rd day of Bureaucracy in the YOLD 3181");
}

module.exports = discordianDate;

Example use:

console.log(discordianDate(new Date(Date.now())));
"Boomtime, the 2nd day of Chaos in the YOLD 3183"

look at calendar; learn about holydays

JotaCode

@print(
  "Today is ",
  @let(1,@add(@switch(@time("mon"),
    0,-1,
    1,30,
    2,58,
    3,89,
    4,119,
    5,150,
    6,180,
    7,211,
    8,242,
    9,272,
    10,303,
    11,333)
  ,@time("mday")),@switch(@print(@time("mon"),"/",@time("mday")),
  "1/29","St. Tib's Day",
  @print(@switch(@mod("%1",5),
    0,"Sweetmorn",
    1,"Boomtime",
    2,"Pungenday",
    3,"Prickle-Prickle",
    4,"Setting Orange"),
  ", ",
  @switch(@idiv("%1",73),
    0,"Chaos",
    1,"Discord",
    2,"Confusion",
    3,"Bureaucracy",
    4,"The Aftermath"),
  " ",
  @add(@mod("%1",73),1),
  ", YOLD ",
  @add(@time("year"),3066))
)),".")

jq

Adapted from #Wren

Works with: jq

Also works with gojq, the Go implementation of jq

Also works with fq, a Go implementation of a large subset of jq

### Gregorian calendar
def isLeapYear(y):
   y%4 == 0 and ((y%100 != 0) or (y%400 == 0));

### Discordian calendar
def seasons:  ["Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"];

def weekdays: ["Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange"];

def apostles: ["Mungday", "Mojoday", "Syaday", "Zaraday", "Maladay"];

def holidays: ["Chaoflux", "Discoflux", "Confuflux", "Bureflux", "Afflux"];

# Input: {year, dayOfYear}
def discordian(date):
  date.year as $y
  | " in the YOLD \($y + 1166)." as $yold
  | { doy: date.dayOfYear, holyday: ""}
  | if isLeapYear($y) and (.doy == 60) then "St. Tib's Day" + $yold
    else if isLeapYear($y) and (.doy > 60) then .doy += -1 else . end
    | .doy += -1
    | .seasonDay = ((.doy % 73) + 1)
    | .seasonNr = ((.doy/73)|floor)
    | .weekdayNr = .doy % 5
    | if .seasonDay == 5 then .holyday = " Celebrate \(apostles[.seasonNr])!"
      elif .seasonDay == 50 then .holyday = " Celebrate \(holidays[.seasonNr])!"
      else .
      end
    | .season = seasons[.seasonNr]
    | .dow = weekdays[.weekdayNr]
    | "\(.dow), day \(.seasonDay) of \(.season)\($yold)\(.holyday)"
    end ;

def dates: [
   "2010-01-01",
   "2010-01-05",
   "2011-02-19",
   "2012-02-28",
   "2012-02-29",
   "2012-03-01",
   "2013-03-19",
   "2014-05-03",
   "2015-05-31",
   "2016-06-22",
   "2016-07-15",
   "2017-08-12",
   "2018-09-19",
   "2018-09-26",
   "2019-10-24",
   "2020-12-08",
   "2020-12-31"
];

dates[]
| (strptime("%Y-%m-%d")
   | {year: .[0], dayOfYear: (1 + .[-1])}) as $dt
| "\(.) = \(discordian($dt))"
Output:

As for Wren.

Julia

using Dates

function discordiandate(year::Integer, month::Integer, day::Integer)
    discordianseasons = ["Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"]
    holidays = Dict(
        "Chaos 5" => "Mungday",
        "Chaos 50" => "Chaoflux",
        "Discord 5" => "Mojoday",
        "Discord 50" => "Discoflux",
        "Confusion 5" => "Syaday",
        "Confusion 50" => "Confuflux",
        "Bureaucracy 5" => "Zaraday",
        "Bureaucracy 50" => "Bureflux",
        "The Aftermath 5" => "Maladay",
        "The Aftermath 50" => "Afflux")
    today = Date(year, month, day)
    isleap = isleapyear(year)
    if isleap && month == 2 && day == 29
        rst = "St. Tib's Day, YOLD " * string(year + 1166)
    else
        dy = dayofyear(today)
        if isleap && dy >= 60
            dy -= 1
        end
        rst = string(discordianseasons[div(dy, 73) + 1], " ", rem(dy, 73)) # day
        if haskey(holidays, rst)
            rst *= " ($(holidays[rst]))" # if holiday
        end
        rst *= ", YOLD $(year + 1166)" # year
    end
    return rst
end

@show discordiandate(2017, 08, 15)
@show discordiandate(1996, 02, 29)
@show discordiandate(1996, 02, 19)
Output:
discordiandate(2017, 8, 15) = "Bureaucracy 8, YOLD 3183"
discordiandate(1996, 2, 29) = "St. Tib's Day, YOLD 3162"
discordiandate(1996, 2, 19) = "Chaos 50 (Chaoflux), YOLD 3162"

Kotlin

Translation of: Java
import java.util.Calendar
import java.util.GregorianCalendar

enum class Season {
    Chaos, Discord, Confusion, Bureaucracy, Aftermath;
    companion object { fun from(i: Int) = values()[i / 73] }
}
enum class Weekday {
    Sweetmorn, Boomtime, Pungenday, Prickle_Prickle, Setting_Orange;
    companion object { fun from(i: Int) = values()[i % 5] }
}
enum class Apostle {
    Mungday, Mojoday, Syaday, Zaraday, Maladay;
    companion object { fun from(i: Int) = values()[i / 73] }
}
enum class Holiday {
    Chaoflux, Discoflux, Confuflux, Bureflux, Afflux;
    companion object { fun from(i: Int) = values()[i / 73] }
}

fun GregorianCalendar.discordianDate(): String {
    val y = get(Calendar.YEAR)
    val yold = y + 1166

    var dayOfYear = get(Calendar.DAY_OF_YEAR)
    if (isLeapYear(y)) {
        if (dayOfYear == 60)
            return "St. Tib's Day, in the YOLD " + yold
        else if (dayOfYear > 60)
            dayOfYear--
    }

    val seasonDay = --dayOfYear % 73 + 1
    return when (seasonDay) {
        5 -> "" + Apostle.from(dayOfYear) + ", in the YOLD " + yold
        50 -> "" + Holiday.from(dayOfYear) + ", in the YOLD " + yold
        else -> "" + Weekday.from(dayOfYear) + ", day " + seasonDay + " of " + Season.from(dayOfYear) + " in the YOLD " + yold
    }
}

internal fun test(y: Int, m: Int, d: Int, result: String) {
    assert(GregorianCalendar(y, m, d).discordianDate() == result)
}

fun main(args: Array<String>) {
    println(GregorianCalendar().discordianDate())

    test(2010, 6, 22, "Pungenday, day 57 of Confusion in the YOLD 3176")
    test(2012, 1, 28, "Prickle-Prickle, day 59 of Chaos in the YOLD 3178")
    test(2012, 1, 29, "St. Tib's Day, in the YOLD 3178")
    test(2012, 2, 1, "Setting Orange, day 60 of Chaos in the YOLD 3178")
    test(2010, 0, 5, "Mungday, in the YOLD 3176")
    test(2011, 4, 3, "Discoflux, in the YOLD 3177")
    test(2015, 9, 19, "Boomtime, day 73 of Bureaucracy in the YOLD 3181")
}

MAD

          R   DISCORDIAN DATE CALCULATION
          R
          R   PUNCH CARD SHOULD CONTAIN -
          R   MM/DD/YYYY
          R   IN GREGORIAN CALENDAR 
          
            NORMAL MODE IS INTEGER
            
            VECTOR VALUES MLENGT = 
          0   0,0,31,59,90,120,151,181,212,243,273,304,334
            VECTOR VALUES TIBS = 
          0   $31HSAINT TIBS DAY IN THE Y.O.L.D. ,I4*$
            VECTOR VALUES DISDAT = 
          0   $C,6H, DAY ,I2,S1,3HOF ,C,S1,16HIN THE Y.O.L.D. ,I4*$
            
            VECTOR VALUES DISDAY = $SWEETMORN$, $BOOMTIME$,
          0   $PUNGENDAY$, $PRICKLE-PRICKLE$, $SETTING ORANGE$
            VECTOR VALUES DISSSN = $CHAOS$, $DISCORD$,
          0   $CONFUSION$, $BUREAUCRACY$, $THE AFTERMATH$
          
            VECTOR VALUES CLDAY  = $10HCELEBRATE ,C,3HDAY*$
            VECTOR VALUES CLFLUX = $10HCELEBRATE ,C,4HFLUX*$
            VECTOR VALUES HOLY5  = $MUNG$,$MOJO$,$SYA$,$ZARA$,$MALA$
            VECTOR VALUES HOLY50 = $CHAO$,$DISCO$,$CONFU$,$BURE$,$AF$
          
            READ FORMAT GREG,GMONTH,GDAY,GYEAR
            VECTOR VALUES GREG = $2(I2,1H/),I4*$

            WHENEVER GMONTH.E.2 .AND. GDAY.E.29
                PRINT FORMAT TIBS, GYEAR + 1166
            OTHERWISE
                YRDAY = MLENGT(GMONTH)+GDAY
                SEASON = YRDAY/73
                DAY = YRDAY-SEASON*73
                WKDAY = (YRDAY-1)-(YRDAY-1)/5*5
                PRINT FORMAT DISDAT, DISDAY(WKDAY), DAY,
          0         DISSSN(SEASON), GYEAR + 1166
                WHENEVER DAY.E.5
                    PRINT FORMAT CLDAY, HOLY5(SEASON)
                OR WHENEVER DAY.E.50
                    PRINT FORMAT CLFLUX, HOLY50(SEASON)
                END OF CONDITIONAL 
            END OF CONDITIONAL          
            END OF PROGRAM
Output:
01/05/2005
SETTING ORANGE, DAY  5 OF CHAOS IN THE Y.O.L.D. 3171
CELEBRATE MUNGDAY

09/26/1995
PRICKLE-PRICKLE, DAY 50 OF BUREAUCRACY IN THE Y.O.L.D. 3161
CELEBRATE BUREFLUX

02/29/1996
SAINT TIBS DAY IN THE Y.O.L.D. 3162

12/05/2020
PRICKLE-PRICKLE, DAY 47 OF THE AFTERMATH IN THE Y.O.L.D. 3186


Maple

convertDiscordian := proc(year, month, day)
	local days31, days30, daysThisYear, i, dYear, dMonth, dDay, seasons, week, dayOfWeek;
	days31 := [1, 3, 5, 7, 8, 10, 12];
	days30 := [4, 6, 9, 11];
	if month < 1 or month >12 then
		error "Invalid month: %1", month;
	end if;
	if (member(month, days31) and day > 31) or (member(month, days30) and day > 30) or (month = 2 and day > 29) or day < 1 then
		error "Invalid date: %1", day;
	end if;
	dYear := year + 1166;
	if month = 2 and day = 29 then
		printf("The date is St. Tib's Day, YOLD %a.\n", dYear);
	else
		seasons := ["Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"];
		week := ["Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange"];
		daysThisYear := 0;
		for i to month-1 do
			if member(i, days31) then
				daysThisYear := daysThisYear + 31;
			elif member(i, days30) then
				daysThisYear := daysThisYear + 30;
			else
				daysThisYear := daysThisYear + 28;
			end if;
		end do;
		daysThisYear := daysThisYear + day -1;
		dMonth := seasons[trunc((daysThisYear) / 73)+1];
		dDay := daysThisYear mod 73 +1;
		dayOfWeek := week[daysThisYear mod 5 +1];
		printf("The date is %s %s %s, YOLD %a.\n", dayOfWeek, dMonth, convert(dDay, ordinal), dYear);
	end if;
end proc:

convertDiscordian (2016, 1, 1);
convertDiscordian (2016, 2, 29);
convertDiscordian (2016, 12, 31);
Output:
The date is Sweetmorn Chaos first, YOLD 3182.
The date is St. Tib's Day, YOLD 3182.
The date is Setting Orange The Aftermath 73rd, YOLD 3182.

Mathematica / Wolfram Language

DiscordianDate[y_, m_, d_] := Module[{year = ToString[y + 1166], month = m, day = d},

  DMONTHS = {"Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"};
  DDAYS = {"Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange"};
  DayOfYear = DateDifference[{y} ,{y, m, d}] + 1;
  LeapYearQ = (Mod[#, 4]== 0 && (Mod[#, 100] != 0 || Mod[#, 400] == 0))&@ y;

  If [ LeapYearQ && month == 2 && day == 29,
    Print["Today is St. Tib's Day, YOLD ", ]
  ,
    If [ LeapYearQ && DayOfYear >= 60, DayOfYear -= 1 ];
     {season, dday} = {Quotient[DayOfYear, 73], Mod[DayOfYear, 73]};
     Print["Today is ", DDAYS[[Mod[dday,4] + 1]],", ",DMONTHS[[season+1]]," ",dday,", YOLD ",year]
    ];
]
Output:
DiscordianDate[2012,2,28]
-> Today is Prickle-Prickle, Chaos 59, YOLD 3178

DiscordianDate[2012,2,29]
-> Today is St. Tib's Day, YOLD 3178

DiscordianDate[2012,3,1]
-> Today is Setting Orange, Chaos 60, YOLD 3178

Nim

We use a DateTime object as intermediate representation.

import times, strformat

const

  DiscordianOrigin = -1166
  SaintTibsDay = "St. Tib’s Day"

type

  Season = enum
    sCha = (1, "Chaos"), sDis = "Discord", sCon = "Confusion",
    sBur = "Bureaucracy", sAft = "The Aftermath"

  ErisianWeekDay = enum
    eSwe = "Sweetmorn", eBoo = "Boomtime", ePun = "Pungenday",
    ePri = "Prickle-Prickle", eSet = "Setting Orange"

  SeasonDayRange = range[1..73]

  # Description of a discordian date.
  DiscordianDate = object
    year: int
    yearday: YeardayRange
    case isSaintTibsDay: bool
    of false:
      seasondayZero: int
      seasonZero: int
      weekday: ErisianWeekDay
    else:
      nil

#---------------------------------------------------------------------------------------------------

proc toDiscordianDate(gdate: DateTime): DiscordianDate =
  ## Convert a DateTime to a discordian date.
  ## All the time fields are ignored.

  # Create the object.
  result = DiscordianDate(isSaintTibsDay: gdate.isLeapDay)

  # The yearday field is unchanged.
  result.yearday = gdate.yearday

  # The year is simply translated.
  result.year = gdate.year - DiscordianOrigin

  # For remaining fields, we must take in account leap years.
  if not result.isSaintTibsDay:
    var yearday = result.yearday
    if gdate.year.isLeapYear and result.yearday > 59:
      dec yearday
    # Now, we have simply to use division and modulo using the corrected yearday.
    result.seasonZero = yearday div SeasonDayRange.high
    result.seasondayZero = yearday mod SeasonDayRange.high
    result.weekday = ErisianWeekDay(yearday mod 5)

#---------------------------------------------------------------------------------------------------

proc `$`(date: DiscordianDate): string =
  ## Convert a discordian date to a string.
  if date.isSaintTibsDay:
    result = SaintTibsDay
  else:
    result = fmt"{date.weekday}, {Season(date.seasonZero + 1)} {date.seasondayZero + 1}"
  result &= fmt", {date.year} YOLD"

#---------------------------------------------------------------------------------------------------

proc showDiscordianDate(year, month, day: Natural) =
  ## Show the discordian date corresponding to a gregorian date.
  let gdate = initDateTime(year = year, month = Month(month), monthday = day,
                           hour = 0, minute = 0, second = 0)
  echo gdate.format("YYYY-MM-dd"), ": ", $gdate.toDiscordianDate()

#———————————————————————————————————————————————————————————————————————————————————————————————————

showDiscordianDate(2100, 12, 31)
showDiscordianDate(2012, 02, 28)
showDiscordianDate(2012, 02, 29)
showDiscordianDate(2012, 03, 01)
showDiscordianDate(2010, 07, 22)
showDiscordianDate(2012, 09, 02)
showDiscordianDate(2012, 12, 31)
Output:
2100-12-31: Setting Orange, The Aftermath 73, 3266 YOLD
2012-02-28: Prickle-Prickle, Chaos 59, 3178 YOLD
2012-02-29: St. Tib’s Day, 3178 YOLD
2012-03-01: Setting Orange, Chaos 60, 3178 YOLD
2010-07-22: Pungenday, Confusion 57, 3176 YOLD
2012-09-02: Setting Orange, Bureaucracy 26, 3178 YOLD
2012-12-31: Setting Orange, The Aftermath 73, 3178 YOLD

Pascal

program ddate;
{
This program is free software, it's done it's time
and paid for it's crime. You can copy, edit and use this
software under the terms of the GNU GPL v3 or later.

Copyright Pope Englebert Finklestien,
On this day Boomtime, the 71st day of Confusion in the YOLD 3183

This program will print out the current date in Erisian format as specified in

                  P R I N C I P I A   D I S C O R D I A   

If you run it with a date it the command line in european format (dd mm yy) it 
will print the equvolent Discordian date. If you omit the year and  month the 
current Anerisiean month and year as assumed.
 

POPE Englebert Finklestien.
}
uses Sysutils;

var
  YY,MM,DD : word;
  YOLD : Boolean;
  Hedgehog: integer;
  Eris: string;
  snub: string;
  chaotica: string;
  midget: string;
  bob: string;


  Anerisiandaysinmonth: array[1..12] of integer = (31,28,31,30,31,30,31,31,30,31,30,31);



procedure anerisiandate;
{ tHIS JUST GETS THE DATE INTO THE  DD,MM,YY VARIABLES }
begin
    DeCodeDate(date,yy,mm,dd);
end;

procedure BORIS;
{ This just tests to see if we are in a leap year }
var
  snafu : boolean;
begin
  snafu := False;
  if (yy mod 4 = 0) then snafu := True;
  if ((yy mod 100 = 0) and (yy mod 400 <> 0)) then snafu := False;
  if ((snafu) and (mm = 2 ) and (dd=29)) then YOLD := True;
end;

function hodgepodge: integer;
{ This returns the total number of days since the year began.
It doesn't bother with leap years at all.
I get a wierd optical illusion looking at the until in this }
var
  fnord : integer;
begin
   Hedgehog := 1;
   hodgepodge := 0;
   fnord :=0;
   if (mm > 1) then repeat
             fnord := fnord + Anerisiandaysinmonth[Hedgehog];
             Hedgehog := Hedgehog +1;
       until Hedgehog = mm;
   fnord := fnord + dd;
   hodgepodge := fnord;
 end;


function treesaregreen(): string;
{Returns the YOLD as a string}

begin
    treesaregreen := IntTOStr(yy+1166);
end;

 
procedure GRAYFACE;
{This calculates everything, but does not bother much about leap years}
var
   wrestle: integer;
   Thwack: string;
begin
    Hedgehog := hodgepodge;
    wrestle := 0;
    Thwack := 'th';
    {set bob to the name of the holyday or St. Tibs day }
    bob := 'St. Tibs Day';         
    if (Hedgehog = 5 )  then bob := 'Mungday';
    if (Hedgehog = 50 ) then bob := 'Chaoflux';
    if (Hedgehog = 78 ) then bob := 'Mojoday';
    if (Hedgehog = 123) then bob := 'Discoflux';
    if (Hedgehog = 151) then bob := 'Syaday';
    if (Hedgehog = 196) then bob := 'Confuflux';
    if (Hedgehog = 224) then bob := 'Zaraday';
    if (Hedgehog = 269) then bob := 'Bureflux';
    if (Hedgehog = 297) then bob := 'Maladay';
    if (Hedgehog = 342) then bob := 'Afflux';
    {Not doing things the usual way
    Lets find the week day and count the number of
	5 day weeks all at the same time}
    while (Hedgehog > 5) do begin 
      Hedgehog := Hedgehog -5;
      wrestle := Wrestle + 1;
    end;
    if (Hedgehog = 1) then snub := 'Sweetmorn'  ;
    if (Hedgehog = 2) then snub := 'BoomTime';
    if (Hedgehog = 3) then snub := 'Pungenday';
    if (Hedgehog = 4) then snub := 'Prickle-Prickle';
    if (Hedgehog = 5) then snub := 'Setting Orange';
	{Now to set the Season name}
    chaotica:='The Aftermath';
    if (wrestle <=57) then chaotica := 'Bureaucracy';
    if ((wrestle = 58) and (Hedgehog < 3)) then chaotica := 'Bureaucracy';
    if (wrestle <= 42) then chaotica := 'Confusion';
    if ((wrestle = 43) and (Hedgehog < 5)) then chaotica := 'Confusion';
    if (wrestle <=28) then chaotica := 'Discord';
    if ((wrestle = 29) and (Hedgehog < 2)) then chaotica := 'Discord';
    if (wrestle <=13) then chaotica := 'Chaos';
    if ((wrestle = 14) and (Hedgehog < 4)) then chaotica := 'Chaos';

	{Now all we need the day of the season}
    wrestle := (wrestle*5)+Hedgehog;
    while (wrestle >73) do wrestle := wrestle -73;
	{pick the appropriate day postfix, allready set to th}
    if (wrestle in [1,21,31,41,51,61,71]) then Thwack:='st';
    if (wrestle in [2,22,32,42,52,62,72]) then Thwack:='nd';
    if (wrestle in [3,23,33,43,53,63,73]) then Thwack:='rd';
	{Check to see if it is a holy day, if so bob will have
	the right holyday name already, including St Tibs Day}
    if (wrestle in [5,50]) then YOLD := True;
	{I love this line of code}
    midget := IntToStr(wrestle) + Thwack;
end;


{The main program starts here}
begin
    anerisiandate;
    if (ParamCount >=1) then dd := StrTOInt(ParamStr(1));
    if (ParamCount >=2) then mm := StrToInt(ParamStr(2));
    if (ParamCount =3) then yy := StrToInt(ParamStr(3));
    BORIS;
    GRAYFACE;
	{ The only thing to bother about is holy days and St Tibs day }
    Eris := 'Today is: ' + snub +' the ' + midget +' day of the season of ' + chaotica;
    if (YOLD) then begin 
	    Eris := 'Celebrate for today, ' + snub + ' the ' + midget + ' day of ' +chaotica + ' is the holy day of ' + bob;
    end;
	{The only place we deal with St. Tibs Day}
    if ((YOLD) and ((mm=2) and (dd=29))) then Eris := 'Celebrate ' + bob + ' Chaos';
	{This next line applies to all possibilities}
    Eris := Eris + ' YOLD ' + treesaregreen;
    WriteLn(Eris);
end.
Output:

 ./ddate
Today is: Setting Orange the 1st day of the season of The Aftermath YOLD 3183
./ddate 12
Celebrate for today, Prickle-Prickle the 5th day of The Aftermath is the holy day of Zaraday YOLD 3183
./ddate 13 5
Today is: Pungenday the 60th day of the season of Confusion YOLD 3183
./ddate 29 2 2020
Celebrate St. Tibs Day Chaos YOLD 3186
 

Perl

Translation of: Raku
use 5.010;
use strict;
use warnings;
use Time::Piece ();

my @seasons = (qw< Chaos Discord Confusion Bureaucracy >, 'The Aftermath');
my @week_days = (qw< Sweetmorn Boomtime Pungenday Prickle-Prickle >, 'Setting Orange');

sub ordinal {
	my ($n) = @_;
	return $n . "th" if int($n/10) == 1;
	return $n . ((qw< th st nd rd th th th th th th>)[$n % 10]);
}
 
sub ddate {
	my $d = Time::Piece->strptime( $_[0], '%Y-%m-%d' );
	my $yold = 'in the YOLD ' . ($d->year + 1166);

	my $day_of_year0 = $d->day_of_year;
 
	if( $d->is_leap_year ) {
		return "St. Tib's Day, $yold" if $d->mon == 2 and $d->mday == 29;
		$day_of_year0-- if $day_of_year0 >= 60; # Compensate for St. Tib's Day
	}
 
	my $weekday = $week_days[ $day_of_year0 % @week_days ];
	my $season = $seasons[ $day_of_year0 / 73 ];
	my $season_day = ordinal( $day_of_year0 % 73 + 1 );

	return "$weekday, the $season_day day of $season $yold";
}
 
say "$_ is " . ddate($_) for qw< 2010-07-22 2012-02-28 2012-02-29 2012-03-01 >;
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

Phix

with javascript_semantics
constant seasons = {"Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"},
         weekday = {"Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange"},
         apostle = {"Mungday", "Mojoday", "Syaday", "Zaraday", "Maladay"},
         holiday = {"Chaoflux", "Discoflux", "Confuflux", "Bureflux", "Afflux"}
 
function discordianDate(sequence dt)
    integer {y,m,d} = dt, 
            leap = is_leap_year(y),
            doy = day_of_year(y,m,d)-1
    string dyear = sprintf("%d",y+1166)
    if leap and m=2 and d=29 then
        return "St. Tib's Day, in the YOLD " & dyear
    end if
    if leap and doy>=60 then
        doy -= 1
    end if
    integer dsday = remainder(doy,73)+1,
            dseason = floor(doy/73+1)
    if dsday=5 then
        return apostle[dseason] & ", in the YOLD " & dyear
    elsif dsday=50 then
        return holiday[dseason] & ", in the YOLD " & dyear
    end if
    string dseas = seasons[dseason],
           dwday = weekday[remainder(doy,5)+1]
    return sprintf("%s, day %d of %s in the YOLD %s", {dwday, dsday, dseas, dyear})
end function

-- test code

sequence dt = {2015,1,1,0,0,0,0,0}
include timedate.e
atom oneday = timedelta(days:=1)
set_timedate_formats({"DD/MM/YYYY"})
for i=1 to 5 do
    printf(1,"%s: %s\n",{format_timedate(dt),discordianDate(dt)})
    dt = adjust_timedate(dt,oneday*72)
    printf(1,"%s: %s\n",{format_timedate(dt),discordianDate(dt)})
    dt = adjust_timedate(dt,oneday)
end for
Output:
"01/01/2015: Sweetmorn, day 1 of Chaos in the YOLD 3181"
"14/03/2015: Pungenday, day 73 of Chaos in the YOLD 3181"
"15/03/2015: Prickle-Prickle, day 1 of Discord in the YOLD 3181"
"26/05/2015: Sweetmorn, day 73 of Discord in the YOLD 3181"
"27/05/2015: Boomtime, day 1 of Confusion in the YOLD 3181"
"07/08/2015: Prickle-Prickle, day 73 of Confusion in the YOLD 3181"
"08/08/2015: Setting Orange, day 1 of Bureaucracy in the YOLD 3181"
"19/10/2015: Boomtime, day 73 of Bureaucracy in the YOLD 3181"
"20/10/2015: Pungenday, day 1 of The Aftermath in the YOLD 3181"
"31/12/2015: Setting Orange, day 73 of The Aftermath in the YOLD 3181"

PHP

<?php
    $Anerisia = array(31,28,31,30,31,30,31,31,30,31,30,31);
    $MONTHS = array("Choas","Discord","Confusion","Bureacracy","The Aftermath");
    $DAYS = array("Setting Orange","Sweetmorn","BoomTime","Pungenday","Prickle-Prickle");
    $Dsuff = array('th','st','nd','rd','th','th','th','th','th','th');
    $Holy5 = array("Mungday","MojoDay","Syaday","Zaraday","Maladay");
    $Holy50 = array("Chaoflux","Discoflux","Confuflux","Bureflux","Afflux");


    

    // Get the current system date and assign to some variables
	$edate = explode(" ",date('Y m j L'));
	$usery = $edate[0];
	$userm = $edate[1];
	$userd = $edate[2];
	$IsLeap = $edate[3];

  // If the user supplied us with a date overide the one we got from the system.
  // If you could get the date from users browser via javascript and then call
  // this script with the users date. ddate.php?y=year&m=month&d=day mostly it
  // won't matter but if the server is in a different time zone to the user
  // There will be occasional incorrect results from the users POV. 

    if (isset($_GET['y']) && isset($_GET['m']) && isset($_GET['d'])) {
        $usery = $_GET['y'];
        $userm = $_GET['m'];
        $userd = $_GET['d'];
        $IsLeap = 0;
        if (($usery%4 == 0) && ($usery%100 >0)) $IsLeap =1;
        if ($usery%400 == 0) $IsLeap = 1;
    }

 // We need to know the total number of days in the year so far

    $userdays = 0;
    $i = 0;
    while ($i < ($userm-1)) {
        
        $userdays = $userdays + $Anerisia[$i];
        $i = $i +1;
    }
    $userdays = $userdays + $userd;

    // We can now work out the full discordian date for most dates
    // PHP does not do integer division, so we use 73.2 as a divisor
    // the value 73.2 works, larger values cause an off-by-one on season
    // changes for the later seasons .
    // This is not needed with the mod operator.

    $IsHolyday = 0;
    $dyear = $usery + 1166;
    $dmonth = $MONTHS[$userdays/73.2];
    $dday = $userdays%73;
	if (0 == $dday) $dday = 73;
    $Dname = $DAYS[$userdays%5];
    $Holyday = "St. Tibs Day";
    if ($dday == 5) {
        $Holyday = $Holy5[$userdays/73.2];
        $IsHolyday =1;
    }
    if ($dday == 50) {
        $Holyday = $Holy50[$userdays/73.2];
        $IsHolyday =1;
    }

  if (($IsLeap ==1) && ($userd ==29) and ($userm ==2)) $IsHolyday = 2;

   // work out the suffix to the day number
   $suff = $Dsuff[$dday%10] ;
   if ((11 <= $dday) && (19 >= $dday)) $suff='th';

    // code to display the date ...

 if ($IsHolyday ==2)
      echo "</br>Celeberate ",$Holyday," ",$dmonth," YOLD ",$dyear;
    if ($IsHolyday ==1)
      echo "</br>Celeberate for today ", $Dname , " The ", $dday,"<sup>",$suff,"</sup>", " day of ", $dmonth , " YOLD " , $dyear , " is the holy day of " , $Holyday;
    if ($IsHolyday == 0)
       echo "</br>Today is " , $Dname , " the " , $dday ,"<sup>",$suff, "</sup> day of " , $dmonth , " YOLD " , $dyear;

 ?>
Output:
ddate.php #23 November 2011
Today is Boomtime the 35th day of The Aftermath YOLD 3177

ddate.php?y=2012&m=2&y=28
Today is Prickle-Prickle the 59th day of Chaos YOLD 3178

ddate.php?y=2012&m=2&y=29
Celeberate St. Tibs Day, Chaos YOLD 3178

ddate.php?y=2017&m=8&d=12
Celeberate for today Prickle-Prickle The 5th day of Bureacracy YOLD 3183 is the holy day of Zaraday

PicoLisp

Translation of: Python
(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) ) ) ) ) )

Pike

Pike includes a Discordian calendar. dates can be converted from any calendar to any other.

> Calendar.Discordian.now()->format_ext_ymd(); 
 Result: "Pungenday, 59 Bureaucracy 3177"
> Calendar.Discordian.Day(Calendar.Day(2011,11,11))->format_ext_ymd();
 Result: "Setting Orange, 23 The Aftermath 3177"
> Calendar.Discordian.Day(Calendar.Badi.Day(168,13,9))->format_ext_ymd(); 
 Result: "Setting Orange, 23 The Aftermath 3177"
> Calendar.Day((Calendar.Discordian.Month()+1)->day(1));
 Result: Day(Thu 20 Oct 2011)

PL/M

Works with: 8080 PL/M Compiler
... under CP/M (or an emulator)
Based on:
Translation of: MAD
...via Algol W
100H: /* DISCORDIAN DATE CALCULATION - TRANSLATION OF MAD (VIA ALGOL W)     */

   /* CP/M SYSTEM CALL AND I/O ROUTINES                                     */
   BDOS:      PROCEDURE( FN, ARG ); DECLARE FN BYTE, ARG ADDRESS; GOTO 5; END;
   PR$CHAR:   PROCEDURE( C ); DECLARE C BYTE;    CALL BDOS( 2, C );  END;
   PR$STRING: PROCEDURE( S ); DECLARE S ADDRESS; CALL BDOS( 9, S );  END;
   PR$NL:     PROCEDURE;   CALL PR$CHAR( 0DH ); CALL PR$CHAR( 0AH ); END;
   PR$NUMBER: PROCEDURE( N ); /* PRINTS A NUMBER IN THE MINIMUN FIELD WIDTH */
      DECLARE N ADDRESS;
      DECLARE V ADDRESS, N$STR ( 6 )BYTE, W BYTE;
      V = N;
      W = LAST( N$STR );
      N$STR( W ) = '$';
      N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
      DO WHILE( ( V := V / 10 ) > 0 );
         N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
      END;
      CALL PR$STRING( .N$STR( W ) );
   END PR$NUMBER;

   /* COMMAND LINE                                                          */
   DECLARE CL$ADDR LITERALLY '80H';          /* ADDRESS OF THE COMMAND LINE */
   DECLARE CL$PTR  ADDRESS;     /* POINTER TO THE CURRENT COMMAND LINE CHAR */
   DECLARE CL$CHAR BASED CL$PTR BYTE;     /* CURRENT COMMAND LINE CHARACTER */
   DECLARE CL$LEN  ADDRESS;                   /* LENGTH OF THE COMMAND LINE */

   /* INITIALISES THE COMMAND LINE VARIABLES                                */
   CL$INIT: PROCEDURE;
      CL$PTR = CL$ADDR;
      CL$LEN = CL$CHAR;
      CL$PTR = CL$PTR + 1;
   END CL$INIT;

   /* READS A NUMBER FROM THE COMMAND LINE, THE TERMINATOR IS IGNORED       */
   CL$NUMBER: PROCEDURE ADDRESS;
      DECLARE N ADDRESS;
      N = 0;
      DO WHILE CL$PTR  <= ( CL$ADDR + CL$LEN ) AND CL$CHAR = ' ';
         CL$PTR = CL$PTR + 1;
      END;
      DO WHILE CL$PTR  <= ( CL$ADDR + CL$LEN ) AND CL$CHAR >= '0'
                                               AND CL$CHAR <= '9';
         N      = ( N * 10 ) + ( CL$CHAR - '0' );
         CL$PTR = CL$PTR + 1;
      END;
      CL$PTR = CL$PTR + 1; /* SKIP THE CHARACTER THAT TERMINATED THE NUMBER */
      RETURN N;
   END CL$NUMBER;

   /* TASK                                                                  */

   DECLARE HOLY5  (  5 )ADDRESS;
   DECLARE HOLY50 (  5 )ADDRESS;
   DECLARE DISDAY (  5 )ADDRESS;
   DECLARE DISSSN (  5 )ADDRESS;
   DECLARE MLENGT ( 13 )ADDRESS
           INITIAL(   0,   0,  31,  59,  90, 120
                  , 151, 181, 212, 243, 273, 304, 334
                  ); 
  
   HOLY5 (0) = .'MUNG$'; HOLY5 (1) = .'MOJO$'; HOLY5 (2) = .'SYA$';
   HOLY5 (3) = .'ZARA$'; HOLY5 (4) = .'MALA$';
   HOLY50(0) = .'CHAO$'; HOLY50(1) = .'DISCO$'; HOLY50(2) = .'CONFU$';
   HOLY50(3) = .'BURE$'; HOLY50(4) = .'AF$';
   DISDAY(0) = .'SWEETMORN$'; DISDAY(1) = .'BOOMTIME$';
   DISDAY(2) = .'PUNGENDAY$'; DISDAY(3) = .'PRICKLE-PRICKLE$';
   DISDAY(4) = .'SETTING ORANGE$';
   DISSSN(0) = .'CHAOS$'; DISSSN(1) = .'DISCORD$'; DISSSN(2) = .'CONFUSION$';
   DISSSN(3) = .'BUREAUCRACY$'; DISSSN(4) = .'THE AFTERMATH$'; 

   /* GET THE GREGORIAN DATE FROM THE COMMAND LINE, NB: NO VALIDATION       */
   DECLARE ( GMONTH, GDAY, GYEAR ) ADDRESS; /* MUST BE IN MM/DD/YYYY FORMAT */
   CALL CL$INIT;
   GMONTH = CL$NUMBER; GDAY = CL$NUMBER; GYEAR = CL$NUMBER;
   CALL PR$NUMBER( GMONTH );CALL PR$CHAR( '/' );CALL PR$NUMBER( GDAY );
   CALL PR$CHAR( '/');CALL PR$NUMBER( GYEAR );CALL PR$NL;

   /* CONVERT AND PRINT THE DATE                                            */
   IF GMONTH = 2 AND GDAY = 29
   THEN DO;
      CALL PR$STRING( .'SAINT TIB''S DAY IN THE Y.O.L.D. $' );
      CALL PR$NUMBER( GYEAR + 1166 );
      END;
   ELSE DO;
      DECLARE ( YRDAY, SEASON, DAY, WKDAY ) ADDRESS;
      YRDAY  = MLENGT(GMONTH)+GDAY;
      SEASON = YRDAY / 73;
      DAY    = YRDAY-SEASON*73;
      WKDAY  = (YRDAY-1) MOD 5;
      CALL PR$STRING( DISDAY(WKDAY) );
      CALL PR$STRING( .', DAY $' );
      CALL PR$NUMBER( DAY );
      CALL PR$STRING( .' OF $' );
      CALL PR$STRING( DISSSN(SEASON) );
      CALL PR$STRING( .' IN THE Y.O.L.D $' );
      CALL PR$NUMBER( GYEAR + 1166 );
      IF      DAY = 5  THEN DO;
         CALL PR$NL;
         CALL PR$STRING( .'CELEBRATE $' );
         CALL PR$STRING( HOLY5(SEASON) );
         CALL PR$STRING( .'DAY$' );
         END;
      ELSE IF DAY = 50 THEN DO;
         CALL PR$NL;
         CALL PR$STRING( .'CELEBRATE $' );
         CALL PR$STRING( HOLY50(SEASON) );
         CALL PR$STRING( .'FLUX$' );
      END;
   END;
   CALL PR$NL;

EOF
Output:

With the command line: DISCORD 03/29/2023:

3/29/2023
PUNGENDAY, DAY 15 OF DISCORD IN THE Y.O.L.D 3189

PowerBASIC

#COMPILE EXE
#DIM ALL

'change this for systems that use a different character
$DATESEP = "-"

FUNCTION day(date AS STRING) AS LONG
    'date is same format as date$
    DIM tmpdash1 AS LONG, tmpdash2 AS LONG
    tmpdash1 = INSTR(date, $DATESEP)
    tmpdash2 = INSTR(-1, date, $DATESEP)
    FUNCTION = VAL(MID$(date, tmpdash1 + 1, tmpdash2 - tmpdash1 - 1))
END FUNCTION

FUNCTION month(date AS STRING) AS LONG
    'date is same format as date$
    DIM tmpdash AS LONG
    tmpdash = INSTR(date, $DATESEP)
    FUNCTION = VAL(LEFT$(date, tmpdash - 1))
END FUNCTION

FUNCTION year(date AS STRING) AS LONG
    'date is same format as date$
    DIM tmpdash AS LONG
    tmpdash = INSTR(-1, date, $DATESEP)
    FUNCTION = VAL(MID$(date, tmpdash + 1))
END FUNCTION

FUNCTION julian(date AS STRING) AS LONG
    'date is same format as date$
    'doesn't account for leap years (not needed for ddate)
    'days preceding 1st of month
    '   jan feb mar apr may  jun  jul  aug  sep  oct  nov  dec
    DATA 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
    FUNCTION = VAL(READ$(month(date))) + day(date)
END FUNCTION

FUNCTION PBMAIN () AS LONG
    'Season names
    DATA "Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"
    'Weekdays
    DATA "Setting Orange", "Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle"

    DIM dyear AS LONG, dseason AS STRING, dday AS LONG, dweekday AS STRING
    DIM tmpdate AS STRING, jday AS LONG, result AS STRING

    IF LEN(COMMAND$) THEN
        tmpdate = COMMAND$
    ELSE
        tmpdate = DATE$
    END IF
    dyear = year(tmpdate) + 1166
    IF (2 = month(tmpdate)) AND (29 = day(tmpdate)) THEN
        result = "Saint Tib's Day, " & STR$(dyear) & " YOLD"
    ELSE
        jday = julian(tmpdate)
        dseason = READ$((jday \ 73) + 1)
        dday = (jday MOD 73)
        IF 0 = dday THEN dday = 73
        dweekday = READ$((jday MOD 5) + 6)
        result = dweekday & ", " & dseason & " " & TRIM$(STR$(dday)) & ", " & TRIM$(STR$(dyear)) & " YOLD"
    END IF

    ? result
END FUNCTION

PowerShell

Works with: powershell version 2
function ConvertTo-Discordian ( [datetime]$GregorianDate )
{
$DayOfYear = $GregorianDate.DayOfYear
$Year = $GregorianDate.Year + 1166
If ( [datetime]::IsLeapYear( $GregorianDate.Year ) -and $DayOfYear -eq 60 )
    { $Day = "St. Tib's Day" }
Else
    {
    If ( [datetime]::IsLeapYear( $GregorianDate.Year ) -and $DayOfYear -gt 60 )
        { $DayOfYear-- }
    $Weekday = @( 'Sweetmorn', 'Boomtime', 'Pungenday', 'Prickle-Prickle', 'Setting Orange' )[(($DayOfYear - 1 ) % 5 )]
    $Season  = @( 'Chaos', 'Discord', 'Confusion', 'Bureaucracy', 'The Aftermath' )[( [math]::Truncate( ( $DayOfYear - 1 ) / 73 ) )]
    $DayOfSeason = ( $DayOfYear - 1 ) % 73 + 1
    $Day = "$Weekday, $Season $DayOfSeason"
    }
$DiscordianDate = "$Day, $Year YOLD"
return $DiscordianDate
}
 
ConvertTo-Discordian ([datetime]'1/5/2016')
ConvertTo-Discordian ([datetime]'2/29/2016')
ConvertTo-Discordian ([datetime]'12/8/2016')
Output:
Setting Orange, Chaos 5, 3182 YOLD
St. Tib's Day, 3182 YOLD
Boomtime, The Aftermath 50, 3182 YOLD

Prolog

Works with: SWI Prolog
% See https://en.wikipedia.org/wiki/Discordian_calendar

main:-
    test(2022, 4, 20),
    test(2020, 5, 24),
    test(2020, 2, 29),
    test(2019, 7, 15),
    test(2025, 3, 19),
    test(2017, 12, 8).

test(Gregorian_year, Gregorian_month, Gregorian_day):-
    ddate(Gregorian_year, Gregorian_month, Gregorian_day,
          Discordian_date),
    format('~|~`0t~d~2+-~|~`0t~d~2+-~|~`0t~d~2+: ~w~n', [Gregorian_year,
           Gregorian_month, Gregorian_day, Discordian_date]).

ddate(Gregorian_year, 2, 29, Discordian_date):-
    convert_year(Gregorian_year, Discordian_year),
    swritef(Discordian_date, 'St. Tib\'s Day in the YOLD %w',
            [Discordian_year]),
    !.
ddate(Gregorian_year, Gregorian_month, Gregorian_day,
      Discordian_date):-
    convert_year(Gregorian_year, Discordian_year),
    day_of_year(Gregorian_month, Gregorian_day, Daynum),
    Season is Daynum//73,
    Weekday is Daynum mod 5,
    Day_of_season is 1 + Daynum mod 73,
    season(Season, Season_name),
    week_day(Weekday, Day_name),
    (holy_day(Season, Day_of_season, Holy_day) ->
        swritef(Discordian_date, '%w, day %w of %w in the YOLD %w. Celebrate %w!',
                [Day_name, Day_of_season, Season_name, Discordian_year, Holy_day])
        ;
        swritef(Discordian_date, '%w, day %w of %w in the YOLD %w',
                [Day_name, Day_of_season, Season_name, Discordian_year])
    ).

convert_year(Gregorian_year, Discordian_year):-
    Discordian_year is Gregorian_year + 1166.

day_of_year(M, D, N):-
    month_days(M, Days),
    N is Days + D - 1.

month_days(1, 0).
month_days(2, 31).
month_days(3, 59).
month_days(4, 90).
month_days(5, 120).
month_days(6, 151).
month_days(7, 181).
month_days(8, 212).
month_days(9, 243).
month_days(10, 273).
month_days(11, 304).
month_days(12, 334).
    
season(0, 'Chaos').
season(1, 'Discord').
season(2, 'Confusion').
season(3, 'Bureacracy').
season(4, 'The Aftermath').

week_day(0, 'Sweetmorn').
week_day(1, 'Boomtime').
week_day(2, 'Pungenday').
week_day(3, 'Prickle-Prickle').
week_day(4, 'Setting Orange').

holy_day(0, 5, 'Mungday').
holy_day(0, 50, 'Chaoflux').
holy_day(1, 5, 'Mojoday').
holy_day(1, 50, 'Discoflux').
holy_day(2, 5, 'Syaday').
holy_day(2, 50, 'Confuflux').
holy_day(3, 5, 'Zaraday').
holy_day(3, 50, 'Bureflux').
holy_day(4, 5, 'Maladay').
holy_day(4, 50, 'Afflux').
Output:
2022-04-20: Setting Orange, day 37 of Discord in the YOLD 3188
2020-05-24: Prickle-Prickle, day 71 of Discord in the YOLD 3186
2020-02-29: St. Tib's Day in the YOLD 3186
2019-07-15: Sweetmorn, day 50 of Confusion in the YOLD 3185. Celebrate Confuflux!
2025-03-19: Pungenday, day 5 of Discord in the YOLD 3191. Celebrate Mojoday!
2017-12-08: Boomtime, day 50 of The Aftermath in the YOLD 3183. Celebrate Afflux!

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

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)

Racket

Translation of: D
#lang racket/base
;;;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;;;; Derived from 'D' Implementation
;;;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(require racket/date racket/match)

(define seasons '(Chaos     Discord   Confusion Bureaucracy     |The Aftermath|))
(define weekday '(Sweetmorn Boomtime  Pungenday Prickle-Prickle |Setting Orange|))
(define apostle '(Mungday   Mojoday   Syaday    Zaraday         Maladay))
(define holiday '(Chaoflux  Discoflux Confuflux Bureflux        Afflux))

(define (ymd->date y m d) (seconds->date (find-seconds 0 0 0 d m y)))
(define (leap-year? y) (with-handlers ((exn? (λ (x) #f))) (= 29 (date-day (ymd->date y 2 29)))))  

(define (discordian-date d)
  (define leap? (leap-year? (date-year d)))
  (define year-day (match* (leap? (date-year-day d))
                     [(#t (? (λ (D) (>= D 59)) d0)) d0]
                     [(_ d0) (add1 d0)]))
  
  (define season-day (modulo year-day 73)) ; season day
  (define (list-ref-season l)
    (define season-index (quotient year-day 73))
    (symbol->string (list-ref l season-index)))
  
  (string-append
   (match* (season-day leap? (date-month d) (date-day d))
     [( _ #t 2 29) "St. Tib's Day,"]
     [((app (match-lambda
              (5 apostle) (50 holiday) (_ #f))
            (and (not #f) special)) _ _  _)
      (string-append (list-ref-season special) ",")]
     [( _  _ _  _)
      (define week-day-name (list-ref weekday (modulo (sub1 year-day) 5)))
      (format "~a, day ~a of ~a" week-day-name season-day (list-ref-season seasons))])
   " in the YOLD " (number->string (+ (date-year d) 1166))))

(displayln (discordian-date (current-date)))

;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;; passing these tests makes me consistent with D implementation
(module+ test
  (require rackunit)
  (define discordian/ymd (compose discordian-date ymd->date))
  (check-equal? (discordian/ymd 2010 7 22) "Pungenday, day 57 of Confusion in the YOLD 3176")
  (check-equal? (discordian/ymd 2012 2 28) "Prickle-Prickle, day 59 of Chaos in the YOLD 3178")
  (check-equal? (discordian/ymd 2012 2 29) "St. Tib's Day, in the YOLD 3178");
  (check-equal? (discordian/ymd 2012 3  1) "Setting Orange, day 60 of Chaos in the YOLD 3178")
  (check-equal? (discordian/ymd 2010 1  5) "Mungday, in the YOLD 3176")
  (check-equal? (discordian/ymd 2011 5  3) "Discoflux, in the YOLD 3177"))
;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~FIN
Output:
Pungenday, day 47 of Confusion in the YOLD 3179

Raku

(formerly Perl 6)

Works with: rakudo version 2015-11-04
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 >;
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

REXX

This REXX version allows the   mm   or   dd   to be one or two digits.

Also, the year can be two or four digits, or it may be omitted.

If the Gregorian date is omitted or specified as an asterisk   (*),   the current date is used.

/*REXX program  converts  a   mm/dd/yyyy    Gregorian date   ───►   a  Discordian date. */
 @day.1= 'Sweetness'                             /*define the 1st day─of─Discordian─week*/
 @day.2= 'Boomtime'                              /*   "    "  2nd  "   "      "       " */
 @day.3= 'Pungenday'                             /*   "    "  3rd  "   "      "       " */
 @day.4= 'Prickle-Prickle'                       /*   "    "  4th  "   "      "       " */
 @day.5= 'Setting Orange'                        /*   "    "  5th  "   "      "       " */

@seas.0= "St. Tib's day,"                        /*define the leap─day of Discordian yr.*/
@seas.1= 'Chaos'                                 /*   "   1st season─of─Discordian─year.*/
@seas.2= 'Discord'                               /*   "   2nd    "    "      "       "  */
@seas.3= 'Confusion'                             /*   "   3rd    "    "      "       "  */
@seas.4= 'Bureaucracy'                           /*   "   4th    "    "      "       "  */
@seas.5= 'The Aftermath'                         /*   "   5th    "    "      "       "  */

parse arg  gM  '/'  gD  "/"  gY .                /*obtain the specified Gregorian date. */
if gM=='' | gM=="," | gM=='*'  then parse value  date("U")   with   gM  '/'  gD  "/"  gY .

gY=left( right( date(), 4), 4 - length(Gy) )gY   /*adjust for two─digit year or no year.*/

                                                 /* [↓]  day─of─year,  leapyear adjust. */
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                           /*   "     "       "     season.       */
dD= doy//73;               if dD==0  then dD= 73 /*   "     "       "     day─of─month. */
if leapyear(gY)  &  gM==2  &  gD==29 then ds=  0 /*is this St. Tib's day  (leapday) ?   */
if ds==0  then dD=                               /*adjust for the Discordian leap day.  */

say space(@day.dW','  @seas.dS dD","  gY + 1166) /*display Discordian date to terminal. */
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
leapyear: procedure;   parse arg y               /*obtain a four─digit Gregorian year.  */
          if y//4  \==  0  then return 0         /*Not  ÷  by 4?   Then not a leapyear. */
          return y//100 \== 0  |  y//400 == 0    /*apply the  100  and  400  year rules.*/
input   when using the (various) following inputs of:
  2/28/2012
  2/29/2012
  3/1/2012
  7/22/2010
  9/2/2012
 12/31/2011
 10/19/2015
 12/31/2100
output   when using the above (various) inputs:
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
Boomtime, Bureaucracy 73, 3181
Setting Orange, The Aftermath 73, 3266

RPL

Works with: Halcyon Calc version 4.2.7
IF DUP2 R→C (29,2) == THEN DROP2 0
   ELSE 
      IF DUP 1 == THEN DROP
      ELSE
         { 31 59 90 120 151 181 212 243 273 304 334 }
         SWAP 1 - GET +
   END END
≫ ‘DQtm’ STO

≪ 1166 + ROT ROT DQtm
  IF DUP THEN
     1 - { "Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange" } 
     OVER 5 MOD 1 + GET  ", " + 
     SWAP { "Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath" } 
     OVER 73 / IP RND 1 + GET " " +
     SWAP 73 MOD 1 + →STR + +
  ELSE DROP "St. Tib's Day" END
  ", YoLD " + SWAP →STR +
≫ ‘DDATE’ STO
Input:
19,1,2023 DDATE
29,2,2024 DDATE
25,12,800 DDATE
Output:
3: "Prickle-Prickle, Chaos 19, YoLD 3189"
2: "St. Tib's Day, YoLD 3190"
1: "Prickle-Prickle, The Aftermath 67, YoLD 1966"

Ruby

require 'date'

class DiscordianDate
  SEASON_NAMES = ["Chaos","Discord","Confusion","Bureaucracy","The Aftermath"]
  DAY_NAMES = ["Sweetmorn","Boomtime","Pungenday","Prickle-Prickle","Setting Orange"]
  YEAR_OFFSET = 1166
  DAYS_PER_SEASON = 73
  DAYS_PER_WEEK = 5
  ST_TIBS_DAY_OF_YEAR = 60

  def initialize(year, month, day)
    gregorian_date = Date.new(year, month, day)
    @day_of_year = gregorian_date.yday

    @st_tibs = false
    if gregorian_date.leap?
      if @day_of_year == ST_TIBS_DAY_OF_YEAR
        @st_tibs = true
      elsif @day_of_year > ST_TIBS_DAY_OF_YEAR
        @day_of_year -= 1
      end
    end

    @season, @day = (@day_of_year-1).divmod(DAYS_PER_SEASON)
    @day += 1     #←              ↑ fixes of-by-one error (only visible at season changes)
    @year = gregorian_date.year + YEAR_OFFSET
  end
  attr_reader :year, :day

  def season
    SEASON_NAMES[@season]
  end

  def weekday
    if @st_tibs
      "St. Tib's Day"
    else
      DAY_NAMES[(@day_of_year - 1) % DAYS_PER_WEEK]
    end
  end

  def to_s
    %Q{#{@st_tibs ? "St. Tib's Day" : "%s, %s %d" % [weekday, season, day]}, #{year} YOLD}
  end
end

Testing:

[[2012, 2, 28], [2012, 2, 29], [2012, 3, 1], [2011, 10, 5], [2015, 10, 19]].each do |date|
  dd = DiscordianDate.new(*date)
  puts "#{"%4d-%02d-%02d" % date} => #{dd}"
end
Output:
2012-02-28 => Prickle-Prickle, Chaos 59, 3178 YOLD
2012-02-29 => St. Tib's Day, 3178 YOLD
2012-03-01 => Setting Orange, Chaos 60, 3178 YOLD
2011-10-05 => Pungenday, Bureaucracy 59, 3177 YOLD
2015-10-19 => Boomtime, Bureaucracy 73, 3181 YOLD

Rust

Compiler: Rust (1.21.0)

Library: chrono
Library: ddate

This example is taken in large part from the ddate crate and used with the permission of the author.

extern crate chrono;

use chrono::NaiveDate;
use std::str::FromStr;

fn main() {
    let date = std::env::args().nth(1).expect("Please provide a YYYY-MM-DD date.");
    println!("{} is {}", date, NaiveDate::from_str(&date).unwrap().to_poee());
}

// The necessary constants for the seasons, weekdays, and holydays.
const APOSTLES: [&str; 5] = ["Mungday", "Mojoday", "Syaday", "Zaraday", "Maladay"];
const HOLYDAYS: [&str; 5] = ["Chaoflux", "Discoflux", "Confuflux", "Bureflux", "Afflux"];
const SEASONS: [&str; 5] = ["Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"];
const WEEKDAYS: [&str; 5] = ["Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange"];

// The necessary constants for the conversion.
const APOSTLE_HOLYDAY: usize = 5;
const CURSE_OF_GREYFACE: i32 = 1166;
const SEASON_DAYS: usize = 73;
const SEASON_HOLYDAY: usize = 50;
const ST_TIBS_DAY: usize = 59;
const WEEK_DAYS: usize = 5;

// This extends the `Datelike` trait of Rust's Chrono crate with a method that
// prints any Datelike type as a String.
impl<T: Datelike> DiscordianDate for T {}
pub trait DiscordianDate: Datelike {
    fn to_poee(&self) -> String {
        let day = self.ordinal0() as usize;
        let leap = self.year() % 4 == 0 && self.year() % 100 != 0 || self.year() % 400 == 0;
        let year = self.year() + CURSE_OF_GREYFACE;

        if leap && day == ST_TIBS_DAY { return format!("St. Tib's Day, in the YOLD {}", year); }

        let day_offset = if leap && day > ST_TIBS_DAY { day - 1 } else { day };

        let day_of_season = day_offset % SEASON_DAYS + 1;

        let season = SEASONS[day_offset / SEASON_DAYS];
        let weekday = WEEKDAYS[day_offset % WEEK_DAYS];

        let holiday = if day_of_season == APOSTLE_HOLYDAY {
            format!("\nCelebrate {}", APOSTLES[day_offset / SEASON_DAYS])
        } else if day_of_season == SEASON_HOLYDAY {
            format!("\nCelebrate {}", HOLYDAYS[day_offset / SEASON_DAYS])
        } else {
            String::with_capacity(0)
        };

        format!("{}, the {} day of {} in the YOLD {}{}",
            weekday, ordinalize(day_of_season), season, year, holiday)
    }
}

/// A helper function to ordinalize a numeral.
fn ordinalize(num: usize) -> String {
    let s = format!("{}", num);

    let suffix = if s.ends_with('1') && !s.ends_with("11") {
        "st"
    } else if s.ends_with('2') && !s.ends_with("12") {
        "nd"
    } else if s.ends_with('3') && !s.ends_with("13") {
        "rd"
    } else {
        "th"
    };

    format!("{}{}", s, suffix)
}
Output:
$ ./ddate -1166-1-1

-1166-1-1 is Sweetmorn, the 1st day of Chaos in the YOLD 0 $ ./ddate 2000-2-28 2000-2-28 is Prickle-Prickle, the 59th day of Chaos in the YOLD 3166 $ ./ddate -4004-2-29 -4004-2-29 is St. Tib's Day, in the YOLD -2838 $ ./ddate 1066-2-28 1066-2-28 is Prickle-Prickle, the 59th day of Chaos in the YOLD 2232 $ ./ddate 1492-3-1 1492-3-1 is Setting Orange, the 60th day of Chaos in the YOLD 2658 $ ./ddate 1492-9-26 1492-9-26 is Prickle-Prickle, the 50th day of Bureaucracy in the YOLD 2658 Celebrate Bureflux $ ./ddate 2012-10-24 2012-10-24 is Boomtime, the 5th day of The Aftermath in the YOLD 3178 Celebrate Maladay $

Scala

Translation of: Python
package rosetta

import java.util.GregorianCalendar
import java.util.Calendar

object DDate extends App {
  private val DISCORDIAN_SEASONS = Array("Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath")
  
  // month from 1-12; day from 1-31
  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) // 2 means February
      "St. Tib's Day " + dyear + " YOLD"
    else {
      var dayOfYear = date.get(Calendar.DAY_OF_YEAR) - 1
      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 + 1, dyear)
    }
  }
  if (args.length == 3)
    println(ddate(args(2).toInt, args(1).toInt, args(0).toInt))
  else if (args.length == 0) {
    val today = Calendar.getInstance
    println(ddate(today.get(Calendar.YEAR), today.get(Calendar.MONTH)+1, today.get(Calendar.DAY_OF_MONTH)))
  } else
    println("usage: DDate [day month year]")
}

Test:

scala rosetta.DDate 2010 7 22
Confusion 57, 3176 YOLD
scala rosetta.DDate 28 2 2012
Chaos 59, 3178 YOLD
scala rosetta.DDate 29 2 2012
St. Tib's Day 3178 YOLD
scala rosetta.DDate 1 3 2012
Chaos 60, 3178 YOLD
scala rosetta.DDate 19 10 2015
Bureaucracy 73, 3181 YOLD

Seed7

$ include "seed7_05.s7i";
  include "time.s7i";
 
const array string: seasons is [0] ("Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath");
const array string: weekday is [0] ("Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange");
const array string: apostle is [0] ("Mungday", "Mojoday", "Syaday", "Zaraday",  "Maladay");
const array string: holiday is [0] ("Chaoflux", "Discoflux", "Confuflux", "Bureflux", "Afflux");
 
const func string: discordianDate (in time: date) is func
  result
    var string: discordianDate is "";
  local
    var integer: dyear is 0;
    var integer: doy is 0;
    var integer: dsday is 0;
  begin
    dyear := date.year + 1166;
    if isLeapYear(date.year) and date.month = 2 and date.day = 29 then
      discordianDate := "St. Tib's Day, in the YOLD " <& dyear;
    else
      doy := dayOfYear(date);
      if isLeapYear(date.year) and doy >= 60 then
        decr(doy);
      end if;
      dsday := doy rem 73; # season day
      if dsday = 5 then
        discordianDate := apostle[doy div 73] <& ", in the YOLD " <& dyear;
      elsif dsday = 50 then
        discordianDate := holiday[doy div 73] <& ", in the YOLD " <& dyear;
      else
        discordianDate := weekday[pred(doy) rem 5] <&
                          ", day " <& dsday <&
                          " of " <& seasons[doy div 73] <&
                          " in the YOLD " <& dyear;
      end if;
    end if;
  end func;

const proc: main is func
  local
    var time: today is time.value;
  begin
    today := time(NOW);
    writeln(strDate(today) <& " as Discordian date: " <& discordianDate(today));
    if  discordianDate(date(2010, 7, 22)) = "Pungenday, day 57 of Confusion in the YOLD 3176" and
        discordianDate(date(2012, 2, 28)) = "Prickle-Prickle, day 59 of Chaos in the YOLD 3178" and
        discordianDate(date(2012, 2, 29)) = "St. Tib's Day, in the YOLD 3178" and
        discordianDate(date(2012, 3,  1)) = "Setting Orange, day 60 of Chaos in the YOLD 3178" and
        discordianDate(date(2010, 1,  5)) = "Mungday, in the YOLD 3176" and
        discordianDate(date(2011, 5,  3)) = "Discoflux, in the YOLD 3177" then
      writeln("Discordian date computation works.");
    end if;
  end func;
Output:
2013-05-12 as Discordian date: Boomtime, day 59 of Discord in the YOLD 3179
Discordian date computation works.

Sidef

Translation of: Perl
require('Time::Piece');

var seasons = %w(Chaos Discord Confusion Bureaucracy The\ Aftermath);
var week_days = %w(Sweetmorn Boomtime Pungenday Prickle-Prickle Setting\ Orange);

func ordinal (n) {
    "#{n}" + (n % 100 ~~ [11,12,13] ? 'th'
                                    : <th st nd rd th th th th th th>[n % 10])
}

func ddate(ymd) {
    var d = %s'Time::Piece'.strptime(ymd, '%Y-%m-%d');
    var yold = "in the YOLD #{d.year + 1166}";

    var day_of_year0 = d.day_of_year;

    if (d.is_leap_year) {
        return "St. Tib's Day, #{yold}" if ([d.mon, d.mday] == [2, 29]);
        day_of_year0-- if (day_of_year0 >= 60); # Compensate for St. Tib's Day
    }

    var weekday = week_days[day_of_year0 % week_days.len];
    var season = seasons[day_of_year0 / 73];
    var season_day = ordinal(day_of_year0 % 73 + 1);

    return "#{weekday}, the #{season_day} day of #{season} #{yold}";
}

%w(2010-07-22 2012-02-28 2012-02-29 2012-03-01).each { |ymd|
    say "#{ymd} is #{ddate(ymd)}"
}
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

Swift

import Foundation

let monthDays = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]
let seasons = ["Chaos", "Discord", "Confusion", "Bureacracy", "The Aftermath"]
let dayNames = ["Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange"]
let holyDays1 = ["Mungday", "Mojoday", "Syaday", "Zaraday", "Maladay"]
let holyDays2 = ["Chaoflux", "Discoflux", "Confuflux", "Bureflux", "Afflux"]

func discordianDate(date: Date) -> String {
    let calendar = Calendar.current
    let year = calendar.component(.year, from: date)
    let month = calendar.component(.month, from: date)
    let day = calendar.component(.day, from: date)
    let discYear = year + 1166
    if month == 2 && day == 29 {
        return "St. Tib's Day in the YOLD \(discYear)"
    }
    let dayOfYear = monthDays[month - 1] + day - 1
    let season = dayOfYear/73
    let weekDay = dayOfYear % 5
    let dayOfSeason = 1 + dayOfYear % 73
    let ddate = "\(dayNames[weekDay]), day \(dayOfSeason) of \(seasons[season]) in the YOLD \(discYear)"
    switch (dayOfSeason) {
    case 5:
        return ddate + ". Celebrate \(holyDays1[season])!"
    case 50:
        return ddate + ". Celebrate \(holyDays2[season])!"
    default:
        return ddate
    }
}

func showDiscordianDate(year: Int, month: Int, day: Int) {
    let calendar = Calendar.current
    let date = calendar.date(from: DateComponents(year: year, month: month, day: day))!
    let ddate = discordianDate(date: date)
    let format = DateFormatter()
    format.dateFormat = "yyyy-MM-dd"
    print("\(format.string(from: date)): \(ddate)")
}

showDiscordianDate(year: 2022, month: 1, day: 20)
showDiscordianDate(year: 2020, month: 9, day: 21)
showDiscordianDate(year: 2020, month: 2, day: 29)
showDiscordianDate(year: 2019, month: 7, day: 15)
showDiscordianDate(year: 2025, month: 3, day: 19)
showDiscordianDate(year: 2017, month: 12, day: 8)
Output:
2022-01-20: Setting Orange, day 20 of Chaos in the YOLD 3188
2020-09-21: Prickle-Prickle, day 45 of Bureacracy in the YOLD 3186
2020-02-29: St. Tib's Day in the YOLD 3186
2019-07-15: Sweetmorn, day 50 of Confusion in the YOLD 3185. Celebrate Confuflux!
2025-03-19: Pungenday, day 5 of Discord in the YOLD 3191. Celebrate Mojoday!
2017-12-08: Boomtime, day 50 of The Aftermath in the YOLD 3183. Celebrate Afflux!

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

Demonstrating:

puts [disdate 2010 7 22]; # Today
puts [disdate 2012 2 28]
puts [disdate 2012 2 29]
puts [disdate 2012 3 1]
Output:
Confusion 57, 3176 YOLD
Chaos 59, 3178 YOLD
St. Tib's Day, 3178 YOLD
Chaos 60, 3178 YOLD

Wren

Translation of: C#
Library: Wren-date
Library: Wren-fmt
import "./date" for Date
import "./fmt" for Fmt

var seasons  = ["Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"]
var weekdays = ["Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange"]
var apostles = ["Mungday", "Mojoday", "Syaday", "Zaraday", "Maladay"]
var holidays = ["Chaoflux", "Discoflux", "Confuflux", "Bureflux", "Afflux"]

var discordian = Fn.new { |date|
    var y = date.year
    var yold = " in the YOLD %(y + 1166)."
    var doy = date.dayOfYear
    if (Date.isLeapYear(y)) {
        if (doy == 60) return "St. Tib's Day" + yold
        if (doy > 60) doy = doy - 1
    }
    doy = doy - 1
    var seasonDay = doy % 73 + 1
    var seasonNr = (doy/73).floor
    var weekdayNr = doy % 5
    var holyday = ""
    if (seasonDay == 5)  holyday = " Celebrate %(apostles[seasonNr])!"
    if (seasonDay == 50) holyday = " Celebrate %(holidays[seasonNr])!"
    var season = seasons[seasonNr]
    var dow = weekdays[weekdayNr]
    return Fmt.swrite("$s, day $s of $s$s$s", dow, seasonDay, season, yold, holyday)
}

var dates = [
   "2010-01-01",
   "2010-01-05",
   "2011-02-19",
   "2012-02-28",
   "2012-02-29",
   "2012-03-01",
   "2013-03-19",
   "2014-05-03",
   "2015-05-31",
   "2016-06-22",
   "2016-07-15",
   "2017-08-12",
   "2018-09-19",
   "2018-09-26",
   "2019-10-24",
   "2020-12-08",
   "2020-12-31"
]

for (date in dates) {
    var dt = Date.parse(date)
    System.print("%(date) = %(discordian.call(dt))")
}
Output:
2010-01-01 = Sweetmorn, day 1 of Chaos in the YOLD 3176. 
2010-01-05 = Setting Orange, day 5 of Chaos in the YOLD 3176. Celebrate Mungday!
2011-02-19 = Setting Orange, day 50 of Chaos in the YOLD 3177. Celebrate Chaoflux!
2012-02-28 = Prickle-Prickle, day 59 of Chaos in the YOLD 3178. 
2012-02-29 = St. Tib's Day in the YOLD 3178.
2012-03-01 = Setting Orange, day 60 of Chaos in the YOLD 3178. 
2013-03-19 = Pungenday, day 5 of Discord in the YOLD 3179. Celebrate Mojoday!
2014-05-03 = Pungenday, day 50 of Discord in the YOLD 3180. Celebrate Discoflux!
2015-05-31 = Sweetmorn, day 5 of Confusion in the YOLD 3181. Celebrate Syaday!
2016-06-22 = Pungenday, day 27 of Confusion in the YOLD 3182. 
2016-07-15 = Sweetmorn, day 50 of Confusion in the YOLD 3182. Celebrate Confuflux!
2017-08-12 = Prickle-Prickle, day 5 of Bureaucracy in the YOLD 3183. Celebrate Zaraday!
2018-09-19 = Boomtime, day 43 of Bureaucracy in the YOLD 3184. 
2018-09-26 = Prickle-Prickle, day 50 of Bureaucracy in the YOLD 3184. Celebrate Bureflux!
2019-10-24 = Boomtime, day 5 of The Aftermath in the YOLD 3185. Celebrate Maladay!
2020-12-08 = Boomtime, day 50 of The Aftermath in the YOLD 3186. Celebrate Afflux!
2020-12-31 = Setting Orange, day 73 of The Aftermath in the YOLD 3186. 

zkl

Translation of: D
fcn discordianDate(y,m,d){
   var [const]
   seasons=T("Chaos","Discord","Confusion","Bureaucracy","The Aftermath"),
   weekday=T("Sweetmorn","Boomtime","Pungenday","Prickle-Prickle","Setting Orange"),
   apostle=T("Mungday","Mojoday","Syaday","Zaraday","Maladay"),
   holiday=T("Chaoflux","Discoflux","Confuflux","Bureflux","Afflux"];
 
   dYear,isLeapYear := y + 1166, Time.Date.isLeapYear(y);
   if(isLeapYear and m==2 and d==29)
      return("St. Tib's Day, in the YOLD " + dYear);

    doy:=Time.Date.nthDayInYear(y,m,d);
    if(isLeapYear and doy>=60) doy-=1;
    dsDay:=(if(doy%73==0) 73 else doy%73); // Season day.
    if(dsDay==5)  return(String(apostle[doy/73],", in the YOLD ",dYear));
    if(dsDay==50) return(String(holiday[doy/73],", in the YOLD ",dYear));
 
    dSeas:=seasons[(if(doy%73==0) doy-1 else doy)/73];
    dWday:=weekday[(doy - 1)%5];
    "%s, day %s of %s in the YOLD %s".fmt(dWday,dsDay,dSeas,dYear);
}
foreach y,m,d in (T(T(2010,7,22), T(2012,2,28), T(2012,2,29), T(2012,3,1),
		    T(2010,1, 5), T(2011,5, 3))){
   "%d-%02d-%02d is -->%s".fmt(y,m,d,discordianDate(y,m,d)).println();
}
Output:
2010-07-22 is -->Pungenday, day 57 of Confusion in the YOLD 3176
2012-02-28 is -->Prickle-Prickle, day 59 of Chaos in the YOLD 3178
2012-02-29 is -->St. Tib's Day, in the YOLD 3178
2012-03-01 is -->Setting Orange, day 60 of Chaos in the YOLD 3178
2010-01-05 is -->Mungday, in the YOLD 3176
2011-05-03 is -->Discoflux, in the YOLD 3177