Calendars
Conversion between calendars
Instructions for Use
Installation
Which files must be installed
Installation with a SD card
First Step
Copying subsg
Copying cvtcar
Copying calfr-xxx
Copying frf
The programs
GRRD - Conversion from Gregorian to Rata Die
RDGR - Conversion from Rata Die into Gregorian.
JAN_2001
FRBIS - Number of leap days preceding the French Revolutionary year N
FRRD - Conversion from French Revolutionary to Rata Die
RDFR - Conversion from Rata Die to French Revolutionary
GRFR - Conversion from Gregorian to French Revolutionary
FRGR - Conversion from French Revolutionary to Gregorian
Printing a French Revolutionary calendar date
FRLONG - Long format date
FRABR - Abbreviated format date
IP - Integer Part
MOD - Modulo
MAINTENANT - Current Date
Decimal Time
H24H10 - Conversion H24 → H10
H10H24 - Conversion H10 → H24
PRH10 - Printing Decimal Time
Various Utilities
N10R - Roman Numbers
NR
JUSTIF - String Justification
SUBSG - Global Substitution
CVTCAR - Character Conversion
License

Calendars

Conversion between calendars

This group of programs applies to three different calendars.

Instructions for Use

For example, you want to know which French Revolutionary date corresponds to June 6th, 1944. Just type any of:

6,061944 GRFR
6,061944 GRFR FRABR
6,061944 GRFR FRLONG

and you learn that it was octidi, 18 prairial CLII. Depending on the command you used, you obtain the result as a number, 1520918, as an abbreviated string « 18 PRA 152 » or a long string « Octidi 18 Prairial CLII ».

The reverse conversion requires you to know the order of the months and to convert the date into a YYYYMMDD number by yourself. For example, if you want to convert décadi 20 brumaire CXXVII, you first have to convert « brumaire » into « 2 » and then, you write:

1270220 FRGR

and the result is 11,111918, which is November 11th, 1918.

Another reform had been proposed, but never put in effect, the decimalisation of time. Each day was divided into 10 hours, each hour into 100 minutes and each minute into 100 seconds. Although this reform was never applied, a few programs allow you to use a decimal time.

Decimal time has the same format as the usual sexagesimal time: H,MMSS. To convert 19 h 45 (or 7 h 45 PM) into decimal, type any of:

19,45 H24H10 PRH10
19,45 H24H10

and the result is either the number 8,2292 or the string "8:22:92".

A last command is MAINTENANT (now), which gives the current day and current time in long format.

Installation

Which files must be installed

If you use a SD card, or if you drag-and-drop into an emulator such as "emu48", you will need SUBSG and CVTCAR. If you use a connection software such as "conn4x", this software performs the transformations processed by SUBSG and CVTCAR so you do not need to install them.

About files ending in "48" and "50": first try this experiment. Type a number with a fractional part (1.5 for example). Then extract its integer part with IP and convert into a string with →STR. If the result is a comma-less string ("1" in the example above), use the 48-ending files. If the result includes a comma (1,), use the 50-ending files.

The files calfr-dbg-48 and calfr-dbg-50 contain 16 menu entries, which allow you to examine and execute separately all programs. On the other side, the files calfr-48 and calfr-50 contain only the 10 necessary directory entries, some programs being stored in other programs' local variables, so the VAR menu is less cluttered.

You can install the frf file or not. If you do not install it, the directory with the conversion programs will use less than 2800 bytes. Using frf will add 4758 bytes. All depends on the available space on your HP computer.

Installation with a SD card

First Step

First, the -51 flag must be set, so the character separating the fractional part from the integer part of a number will be the comma.

Copying subsg

Copy the subsg file to the HP calculator, which gives a string on the stack.

Edit the content of this string. On the second line, replace the "\->" string by an arrow (right-shift zero). Quit the editor and save your edits.

Then convert the string to a program (PRG TYPE OBJ→ or left-shift N E A on the HP-50, or H C A on the HP-48).

Store the result into SUBSG.

Copying cvtcar

Copy the cvtcar file to the HP calculator, which gives a string on the stack.

Then convert the string to a program (PRG TYPE OBJ→).

Store the result into CVTCAR. There is no need to edit the string before converting it into a program.

Copying calfr-xxx

Copy the calfr-xxx file which you find convenient (see above). As before, this results in a string in the stack.

Run CVTCAR to replace trigrams such as "\->" by the corresponding special characters.

Then, convert the string into an object (PRG TYPE OBJ→), but this time, this object is a directory (DIR).

Store the result with the name you prefer.

Try the MAINTENANT (now) function. If you obtain a « DDAYS Error: Invalid Date », that means that you have forgotten to select the decimal comma before converting the string. Now you have to purge the contents of the directory, then purge the directory itself, select the decimal comma and restart with the copying of the calfr-xxx file.

Copying frf

If you want to use the FRF variable, copy the frf file to the calculator, run CVTCAR on this string, convert to an object (this time, this will be a list) and store it with the name FRF. And move it into the directory where you have stored all the conversion programs from calfr-xxx.

The programs

GRRD - Conversion from Gregorian to Rata Die

The Gregorian → RD conversion is processed in two or three steps. Let us take, for example, the 13th September 1515 in the Gregorian Calendar (ten days before the Battle of Marignan, which took place on 13th September 1515, Julian calendar). The first step consists in reaching a date on 1600 or later, with 400-year increments. In this case, this results in 13th September 1915. The three steps are:

This function is a standalone function when provided by the calfr-dbg-nn files, but it is included into GRFR when provided by the calfr-nn files.

calfr-dbg-48, calfr-dbg-50
«
  0 → GR RD
  «
    WHILE GR 100 * FP 10000 * 1600 <
    REPEAT
     ,0004  'GR' STO+
     146097 'RD' STO+
    END 
    1,012001 GR DDAYS RD - JAN_2001 +
  »
calfr-dbg-48, calfr-dbg-50
»

RDGR - Conversion from Rata Die into Gregorian.

This is the same method in three steps, except that the intermediary date is in 2001 or later, instead of just 1600. It could be modified, just change the threshold date.

calfr-dbg-48, calfr-dbg-50
«
  → J
  « 0
    WHILE J JAN_2001 ≤
    REPEAT 
     ,0004 +
     146097 'J' STO+
    END 
    J JAN_2001 - 
    1,012001 SWAP DATE+
    SWAP -
  »
calfr-dbg-48, calfr-dbg-50
»

JAN_2001

This is the Rata Die value for January 1st, 2001. This value is simple to compute. The Rata Die value of January 1st, 1 is obviously 1. We add 2000 years, that is, 2000 x 365 = 730000 days, plus the number of February 29th's in this period. There are 500 years multiple of 4, 15 of which are not leap years. Therefore, there are 485 leap years. And the sum of these numbers gives the result, 730486.

730486

FRBIS - Number of leap days preceding the French Revolutionary year N

Until the year 20, the leap years were computed so that the first day of the year would be on the autumn equinox. The leap years were 3, 7, 11 and 15. Then, starting with year 20, the rule would be Romme's rule, a purely numerical one, like the Gregorian rule, with a 4-modulus, a 100-modulus and a 400-modulus.

In fact, the function uses the modulus rule all the time, and fixes the result for the few cases where the equinoxial rule differs from the modulus rule.

« → A
  « 'A' DECR 4 / IP 
    A 100 / IP - 
    A 400 / IP +
    A 4000 / IP -
    IF { 3 7 11 15 } A IP POS 0 ≠
    THEN 1 +
    END
  »
»

FRRD - Conversion from French Revolutionary to Rata Die

This function is a standalone function, even when provided by the calfr-nn, because it is called by RDFR (or RDGR).

calfr-dbg-48, calfr-dbg-50
« → F
calfr-48, calfr-50
« FRBIS → F FRBIS
  « F 100 MOD
    F 100 / IP 100 MOD 30 * +
    F 10000 / IP 'F' STO
    F 365 * + F FRBIS + 654019 +
  »
»

RDFR - Conversion from Rata Die to French Revolutionary

We start by shifting the RD number to the "zeroth" Vendémiaire of year I. Then, we compute an estimate of the year, by using a 365-day duration, with no leap days. This gives an estimate greater than the actual value. So, we compare the 1st Vendémiaire of this year with the date to translate. If the 1st Vendémiaire is later than the translated date, we go back one year and we iterate. This is done in a loop, because after 1500 years or so, the estimated year can be 2 or 3 more than the actual year, after 365 leap days have accumulated. When we have reached the proper 1st Vendémiaire, we compute the number of days between it and the translated date, which gives the number of months and the day number in the month.

calfr-dbg-48, calfr-dbg-50
«
  0 → J D
  «
    J 10100 FRRD -
    365 / IP 10000 *
    10101 + 'D' STO
    WHILE D FRRD J >
    REPEAT 
      D 10000 - 'D' STO
    END 
    J D FRRD -
    DUP 30 / IP 100 *
    SWAP 30 MOD + D +
  »
calfr-dbg-48, calfr-dbg-50
»

GRFR - Conversion from Gregorian to French Revolutionary

The two conversions GR → RD → FR at once.

calfr-48, calfr-50
« GRRD RDFR »
calfr-dbg-48, calfr-dbg-50
« GRRD RDFR »

FRGR - Conversion from French Revolutionary to Gregorian

The two conversions FR → RD → GR at once.

calfr-48, calfr-50
« FRRD RDGR »
calfr-dbg-48, calfr-dbg-50
« FRRD RDGR »

Printing a French Revolutionary calendar date

Because of its size, the FRF variable is optional and the function printing the date can work no matter whether the variable exists or not.

Each element of the FRF list consists of a digit and a string. The digit indicates if the string begins with a vowel or a consonant and, in the latter case, whether the name is masculine or feminine. And there is the special case of the jour des récompenses (day of rewards) the only case where the noun is plural.

{
"0raisin" "0safran" "1châtaigne" "1colchique"
...
"1vertu" "0génie" "0travail" "2opinion" 
"3récompenses" "1révolution"
}

FRLONG - Long format date

calfr-dbg-48, calfr-dbg-50
« → D
calfr-48, calfr-50
« N10R → D N10R
  « { "Primi" "Duo" "Tri" "Quarti" "Quinti"
        "Sexti" "Septi" "Octi" "Noni" "Déca" }
    D 1 - 10 MOD 1 + GET "di " +
    D 100 MOD + " " +
    { "Vendémiaire" "Brumaire" "Frimaire"
      "Nivôse" "Pluviôse" "Ventôse"
      "Germinal" "Floréal" "Prairial"
      "Messidor" "Thermidor" "Fructidor"
      "jour complémentaire" } 
    D 100 / IP 100 MOD GET + " " +
    D 10000 / IP N10R +
    IF 'FRF' VTYPE 0 ≥
    THEN
      FRF D 100 MOD D 100 / IP 100 MOD 1 - 30 * + GET
      DUP 1 1 SUB
      { " jour du " " jour de la " " jour de l'"
        " jour des " }
      SWAP NUM 47 - GET SWAP 2 30 SUB + +
    END
  »
»

FRABR - Abbreviated format date

« → D
  « D 100 MOD " " +
    { "VND" "BRU" "FRI" "NIV" "PLU" "VNT"
    "GER" "FLO" "PRA" "MES" "THE" "FRU" "S-C" }
    D 100 / IP 100 MOD GET +
    " " + D 10000 / IP +
  »
»

IP - Integer Part

On the HP-50 calculators, taking the integer part of a real number does not give an integer number, but a real number, the fractional part of which is zero. And when converted to a string, this number keeps its decimal comma. To prevent this, we have to use the R→I function. On the other side, on HP-48's, the integer part of a real number is an integer, which has no comma when converted to a string. In addition, the R→I function does not exist on HP-48's.

calfr-50, calfr-dbg-50
IP R→I
calfr-48, calfr-dbg-48
IP

MOD - Modulo

Same thing for the modulus function

calfr-50, calfr-dbg-50
MOD R→I
calfr-48, calfr-dbg-48
MOD

MAINTENANT - Current Date

This code (translation for "NOW") prints the current day and time.

« DATE GRFR FRLONG
" " + TIME H24H10 PRH10 + 21 JUSTIF »

Decimal Time

H24H10 - Conversion H24 → H10

Decimalisation of minutes and seconds as fractions of hours is a standard RPL function. The full decimalisation of hours, minutes and seconds is therefore this function followed by a simple division.

« HMS→ 2,4 /  »

H10H24 - Conversion H10 → H24

The inverse function as H24H10 above.

« 2,4 * →HMS »

PRH10 - Printing Decimal Time

This code prints the decimal time, with the provision that 8,0317 must give "8:03:17", not "8:3:17". It works also for ordinary hours, provided you do not mind having single-digit hours until "9:59:59", instead of "09:59:59".

«  DUP IP ":" +
  SWAP FP 100 * DUP IP
  IF DUP 9 ≤
  THEN "0" SWAP +
  END
  ":" + 
  SWAP FP 100 * IP
  IF DUP 9 ≤
  THEN "0" SWAP +
  END
  + +
»

Various Utilities

N10R - Roman Numbers

Traditionally, the years of the French calendar are written with Roman numerals. Here is the conversion function.

calfr-48, calfr-50
« 
  NR → ←N NR
calfr-dbg-48, calfr-dbg-50
« → ←N
  «
    IF ←N 4000 <
    THEN
      ""
      1 3 START "M" 1000 NR NEXT
      "CM" 900 NR
      "D"  500 NR
      "CD" 400 NR
      1 3 START "C"  100 NR NEXT
      "XC"  90 NR
      "L"   50 NR
      "XL"  40 NR
      1 3 START "X"   10 NR NEXT
      "IX"   9 NR
      "V"    5 NR
      "IV"   4 NR
      1 3 START "I"    1 NR NEXT
    ELSE
      ←N IP →STR
    END
  »
»

NR

The subprogram NR removes a number from the indo-arabic value (←N variable) and adds it to the Roman value (in the stack, at level 3), but checks first that is is allowed. In level 2, we have the transferred value in Roman number and in level 1 we have the same value in indo-arabic.

« DUP
 IF ←N ≤
 THEN '←N' SWAP STO- +
 ELSE DROP2
 END
»

JUSTIF - String Justification

This routine is not closely linked with the French calendar. It allows the proper display of a string in a screen with a given width. For this, it replaces spaces with newlines. The string is in level 2 and the width is in level 1.

I is the index of the current character, I10 is the index of the last encountered linefeed and I32 is the index of the last encountered space. The condition to replace a space by a linefeed consists of the following:

First case, there is at least one space among the first LG characters of the current line. In other words, the expression I32 I10 > is true. The substitution is executed as soon as I overcomes I10 LG +, that is, as soon as I I10 - LG > turns true.

Second case, there are more than LG successive characters without any space. That means that I I10 - LG > has been true for some time. So we execute the substitution on the first space, that is, when I I32 == turns true.

And if you factorise these conditions, you obtain the condition coded below. When we replace a space with a newline, we must update I10. The value of I32 is no longer significant, but this is not a problem.

« 0 0 10 CHR → CH LG I10 I32 NL
  «
   1 CH SIZE  FOR 
     I CH I I SUB
     CASE
       DUP " " ==
         THEN I 'I32' STO DROP
         END
       NL ==
        THEN I 'I10' STO
        END
     END
     IF I I10 - LG >
        I32 I10 > 
        I I32 ==  OR AND 
     THEN
       CH I32 NL REPL 'CH' STO
       I32 'I10' STO
     END
   NEXT
   CH
  »
»

SUBSG - Global Substitution

This function performs a global substitution on a string, to replace a backslash-string, "\->" for example, by the corresponding character . In input, the processed string at level 3, the replaced sequence without backslash at level 2 ("->" for the example above) and the ASCII code at level 1 (141 for the same example).

« 92 CHR ROT + SWAP CHR
  → ch av ap
  « WHILE ch av POS
    REPEAT
      ch 1 OVER av POS 1 - SUB
      ap +
      ch DUP av POS av SIZE +
      OVER SIZE SUB +
      'ch' STO
    END ch
  »
»

CVTCAR - Character Conversion

This function replaces the automatic conversion which occurs when using Conn4x. It substitutes backslash-sequences with the corresponding special character. In addition, it removes the first line %HPHP which seems to bother the computer.

« 
  "<)" 128 SUBSG   "<-" 142 SUBSG   "PI" 156 SUBSG
  "x-" 129 SUBSG   "|v" 143 SUBSG   "GW" 157 SUBSG
  ".V" 130 SUBSG   "|^" 144 SUBSG   "[]" 158 SUBSG
  "v/" 131 SUBSG   "Gg" 145 SUBSG   "oo" 159 SUBSG
  ".S" 132 SUBSG   "Gd" 146 SUBSG   "<<" 171 SUBSG
  "GS" 133 SUBSG   "Ge" 147 SUBSG   "^o" 176 SUBSG
  "|>" 134 SUBSG   "Gn" 148 SUBSG   "Gm" 181 SUBSG
  "pi" 135 SUBSG   "Gh" 149 SUBSG   ">>" 187 SUBSG
  ".d" 136 SUBSG   "Gl" 150 SUBSG   ".x" 215 SUBSG
  "<=" 137 SUBSG   "Gr" 151 SUBSG   "O/" 216 SUBSG
  ">=" 138 SUBSG   "Gs" 152 SUBSG   "Gb" 223 SUBSG
  "=/" 139 SUBSG   "Gt" 153 SUBSG   ":-" 247 SUBSG
  "Ga" 140 SUBSG   "Gw" 154 SUBSG
  "->" 141 SUBSG   "GD" 155 SUBSG
  IF DUP "%%HP" POS
  THEN
    DUP 10 CHR POS 1 +
    OVER SIZE
    SUB
  END
»

License

This code is published under the same terms as Perl: GPL and Artistic License. See the LICENSE file provided in the package.