The Mel calendar is used in the fictional world of Kaldia. Your goal is to convert dates into the Mel calendar.

This calendar has 13 months of 28 days each, plus 1 or 2 extra days after the last month. A year that is divisible by 4 but not by 100, or divisible by 400 has 366 days, and other years have 365 (i.e. our leap year rules, but with years in the Mel calendar).

You should use the month and day name abbreviations:

months: dia vio lis gil ful dyu mel ral zan pal mik fav ruj

days: dia vio lis gil ful dyu mel ral zan pal mik fav ruj ser rav tan lin rez jil din ket len lax nen pin mat kun mir

The extra days outside of any month have the month name of myuxet (no abbreviation here), and the day names are axet and teems, respectively.

0 dia dia is 1988/11/30.

You can take the input date as a string or a (year, month, day) tuple; alternatively, for functions, the parameter can be in your standard library's date type. The output should be a space-separated string.

Test cases

1776-07-04 => -213 ral ket
1859-12-15 => -129 dia rav
1917-04-14 => -72 ful nen
1981-02-04 => -8 lis mik
1988-11-30 => 0 dia dia
1988-12-01 => 0 dia vio
1988-12-28 => 0 vio dia
2017-01-01 => 28 vio ful
2019-04-22 => 30 dyu lis
2019-11-30 => 30 myuxet axet
2019-12-01 => 31 dia dia
2021-11-29 => 32 myuxet axet
2021-11-30 => 32 myuxet teems
2089-11-30 => 101 dia dia
2389-11-30 => 400 myuxet teems

You should be able to handle dates from 1 AD to 9999 AD at least.

Reference implementation in Perl 6

Standard loopholes are forbidden.

  • 3
    \$\begingroup\$ You should probably include in your post that axet and teems are at the end of the year, I was confused until I looked at the link \$\endgroup\$
    – Gymhgy
    May 9, 2019 at 3:45
  • \$\begingroup\$ It has to be a space-separated string. \$\endgroup\$
    – bb94
    May 9, 2019 at 4:19
  • \$\begingroup\$ Can we take input as a three value named tuple or a list of three values each signifying year, month, and day? \$\endgroup\$
    – Gymhgy
    May 9, 2019 at 4:23
  • 1
    \$\begingroup\$ Yes, that's fine. \$\endgroup\$
    – bb94
    May 9, 2019 at 4:24
  • \$\begingroup\$ May we output month and day in Title Case? -213 Ral Ket? \$\endgroup\$
    – Adám
    May 9, 2019 at 4:59

7 Answers 7


Perl 6, 174 bytes

{~(.year,(|[X]("diaviolisgilfuldyumelralzanpalmikfavrujserravtanlinrezjildinketlenlaxnenpinmatkunmir".comb(3)xx 2)[^364],|("myuxet"X <axet teems>))[.day-of-year-1])}o*-726436

Try it online!

Generate a list of all the valid dates and then indexes the day of the year into that list.


{                                                   }  # Anonymous code block
                                                     o*-726436  # Subtract some days from the input
  (.year,                               # Output the year
           [X]("...".comb(3))[^365]     # Then produce a list of all months/days
         (|                        ,
          |("myuxet"X <axet teems>))    # And the extra days
                                    [.day-of-year-1]   # And get the current date
 ~   # Stringify the list

Ruby, 199 195 193 bytes

Oof, only 23 27 29 bytes saved over the sample Perl code...

-4 bytes from @NickKennedy.

-2 bytes from @Neil.

->d{d-=62764e6;y=d.yday;s="diaviolisgilfuldyumelralzanpalmikfavrujserravtanlinrezjildinketlenlaxnenpinmatkunmir".scan /.../;[d.year,y<364?s[y/28]:"myuxet",(y<364?s:%w[axet teems])[y%28-1]]*' '}

Try it online!


Japt -S, 148 bytes

ÐUVW;f1Uf -726436
-ÐTT i1Ui¹z864e5
`¹avio¦sgÅ~ldyu´llzpal·kfavruj rvt¦nzjÅanket¤nlaxnpµtkun·r`pD ò3
[Ui Vz28 gW¯D p"myuxet")VgWp"axet"`ems`]

Saved 4 bytes thanks to @Shaggy. +A lot more bytes due to bug-fixes. Takes months as 0-indexed numbers.

Japt does have built-in date handling, but it's not very good. Seriously, 34 bytes to initialize a date, then subtract days from it, and then calculate which day of the year it is?

Try it

ÐUVW;                Initialize date object with given inputs
f1Uf -726436         Subtract 726436 days; Store in variable 'U'
-ÐTT i1Ui¹z864e5     Store the day of year in variable 'V'
`...`                Compressed string of all the days
  pD                 Repeated 13 times
    ò3               Split into chunks, where each chunks is 3 chars long, store in variable 'W'
[Ui                  Year
Vz28 gW¯D p"myuxet") Month
VgWp"axet"`ems`]    Day
  • 1
    \$\begingroup\$ Due to the (unnecessarily) strict output format, this should be "Japt -S". You can save 2 bytes by replacing both occurrences of 13 with D. I'll take another look in the morning (when I'm not down the pub, on my phone) to see if I can see any other savings but have a +1 in the meantime for beating Jelly by a significant margin. \$\endgroup\$
    – Shaggy
    May 9, 2019 at 22:53
  • \$\begingroup\$ Just spotted the sT; there's a shortcut for that ;) \$\endgroup\$
    – Shaggy
    May 9, 2019 at 23:00
  • \$\begingroup\$ Sadly, it looks like your byte count is off; TIO is counting in SBCS instead of UTF-8. \$\endgroup\$
    – Shaggy
    May 9, 2019 at 23:35

Jelly, 181 164 bytes


Try it online!

Jelly has no built-in date handling, so this falls back on the functionality within Python’s time module.


“Bƥ...⁵ṣ»                      | Compressed string "diact viol lisk gild full dyu mela rale zanja palay miked fava ruj ser rave tanas linac rez jilt dinar ket lend lax nene pinas mat kune mire"
         Ḳ                     | split at spaces
          ḣ€3                  | first 3 characters of each
                 Ɗ             | following links as a monad
             ḣ13               |    first 13
                p              |    Cartesian product (with all 28)
                 ;           ¤ | concatenate to:
                  “¬...ị»      |   compressed string "myuxet axet teems"
                         Ḳ     |   split at spaces
                            Ɗ  |   following two links as a monad
                          Ḣ    |     head
                           p   |     Cartesian product (with last two)

“Ç...Ḣ»                             | Compressed string 'time  .local ( .mk ( .strp ("'
       Ḳ                            | split at spaces
        jḢ$                         | join using first item (i.e. time)
           ;                        | concatenate to input
            ;“"...)”                | concatenate this to '","%Y%m%d"))+3499e5)'
                    ŒV              | eval as Python
                      m7            | take every 7th item (year and day in year)
                                ʋ/  | reduce using following links as a dyad
                        _2ȷ         |   subtract 2000 (from first value, the year)
                           ;ị¢$}    |   concatenate with right argument (day in year) indexed into above link
                                  K | join with spaces
  • 1
    \$\begingroup\$ "this falls back on the functionality within Python’s time module." Ah, smart! I was trying to make an answer in 05AB1E (also lacking date builtins), and although I was able to get the amount of days between 1988-11-30 and the input-date, it wasn't really useful since I need the date-difference (years, months, and days) instead of days-difference. I have done a few other date related challenges in 05AB1E in the past (i.e. this one and some derivatives). I might try again with part of the code as compressed Python, being inspired by you. :) \$\endgroup\$ May 9, 2019 at 13:11
  • \$\begingroup\$ Let me guess: the first string (diact viol lisk...) is written weirdly to compress better? \$\endgroup\$
    – bb94
    May 11, 2019 at 7:48
  • \$\begingroup\$ @bb94 yes it uses the shortest dictionary word for each where one is available. \$\endgroup\$ May 11, 2019 at 7:50
  • \$\begingroup\$ That's actually really clever. \$\endgroup\$
    – bb94
    May 11, 2019 at 7:51

C# (Visual C# Interactive Compiler), 247 bytes

n=>$"{(n=n.AddDays(4049)).Year-2e3} {((k=n.DayOfYear-1)<365?s.Substring(k/28*3,3):"myuxet")} {(k<365?s.Substring(k%28*3,3):k<366?"axets":"teems")}";var s="diaviolisgilfuldyumelralzanpalmikfavrujserravtanlinrezjildinketlenlaxnenpinmatkunmir";int k;

Try it online!


JavaScript (ES6), 297 269 252 249 245 bytes

d=>(d=new Date(+d+3498336e5),d=(d-Date.UTC(y=d.getUTCFullYear(a=`diaviolisgilfuldyumelralzanpalmikfavrujserravtanlinrezjildinketlenlaxnenpinmatkunmir`.match(/.../g))))/864e5,y-2e3+` ${d<364?a[d/28|0]+` `+a[d%28]:`myuxet ${d&1?`teems`:`axet`}`}`)
<input type=date oninput=o.textContent=f(this.valueAsDate)><pre id=o>

Takes input as a JavaScript date object in UTC (would be 1 byte less as a JavaScript timestamp number). Edit: Saved 3 7 bytes thanks to @Arnauld.

Try it online! if the snippet still isn't working for you for some reason.

  • \$\begingroup\$ Unfortunately, I get something like 30 dyu undefined for this on Firefox. \$\endgroup\$
    – bb94
    May 10, 2019 at 1:16
  • \$\begingroup\$ Same here on chrome \$\endgroup\$
    – Gymhgy
    May 10, 2019 at 3:20
  • \$\begingroup\$ @bb94 Odd, I use Firefox... \$\endgroup\$
    – Neil
    May 10, 2019 at 9:17
  • \$\begingroup\$ @EmbodimentofIgnorance I've tweaked the snippet slightly, does that help? \$\endgroup\$
    – Neil
    May 10, 2019 at 9:22
  • 1
    \$\begingroup\$ @Arnauld Yeah, I had just come to the same conclusion. Fortunately Date.UTC is the same length as new Date! \$\endgroup\$
    – Neil
    May 10, 2019 at 9:48

Haskell, 387 373 372 bytes

import Data.Time.Calendar
t(a:b:c:r)=[a,b,c]:t r
t _=[]
a y=map(show y++)$[' ':m++' ':d|m<-take 13 w,d<-w]++" myuxet axet":[" myuxet teems"|y%4<1,y%400<1||y%100>0]
f d|n<-read.show$diffDays d$fromGregorian 1988 11 30=last$(a=<<[0..])!!n:[(reverse.a=<<[-1,-2..])!!(-n-1)|n<0]

Try it online!

Takes input as a Day object.

This was pretty fun to write! Basic idea is to build a list of dates and index into it for the result. Function a takes a year and outputs every date in that year in chronological order. Function f expands on a concatenating them together for successive years starting at 0. The trick is that for dates before the epoch we need to traverse backwards starting from the year -1 so we pass a values -1,-2... and reverse each list individually before concatenating them together. Finally, in function f we calculate the number of days between the epoch and our date (converting it from Integer to Int) and index into our list, taking care to fix our index if it's negative.

EDIT: golfed it down (-14)

EDIT 2: golfed down the day/month names list (-1)


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.