root/src/date.rs

// date.rs
//
// Copyright 2021-2023 nee <nee-git@patchouli.garden>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// SPDX-License-Identifier: GPL-3.0-or-later

use chrono::prelude::*;

#[derive(Debug, PartialEq)]
/// French Revolutionary Calendar date.
/// Unless gregorian is specified all methods return FR day/month/year numbers.
pub struct FrDate {
    pub(crate) year: i32,
    /// starts at 0, 12 is festivities
    pub(crate) month: u32,
    /// day of the month, goes from 0-29
    pub(crate) day: u32,
}

fn is_leap(year: i32) -> bool {
    ((year % 4) == 0) && (((year % 100) != 0) || ((year % 400) != 0))
}

type DayName = (&'static str, (&'static str, &'static str));
pub fn day_name_label((fr, _): DayName) -> &'static str {
    fr
}
pub fn day_wiki_link((_, (wiki_title, _)): DayName) -> String {
    String::new() + "https://en.wikipedia.org/wiki/" + &wiki_title.replace(' ', "_")
}
pub fn day_wiki_label((_, (_, wiki_label)): DayName) -> &'static str {
    wiki_label
}

const SEPT_21: u32 = 264;
const SEPT_22: u32 = 265;
const YEAR_FLIP_DAY: u32 = 101;
impl From<NaiveDate> for FrDate {
    // gregorian -> frdate conversion
    fn from(date: NaiveDate) -> FrDate {
        let greg_flip_day = if is_leap(date.year()) {
            SEPT_22
        } else {
            SEPT_21
        };
        if date.ordinal() > greg_flip_day {
            return FrDate {
                year: date.year() - 1791,
                month: (date.ordinal() - greg_flip_day - 1) / 30,
                day: (date.ordinal() - greg_flip_day - 1) % 30,
            };
        }
        FrDate {
            year: date.year() - 1792,
            month: (date.ordinal() + YEAR_FLIP_DAY - 1) / 30,
            day: (date.ordinal() + YEAR_FLIP_DAY - 1) % 30,
        }
    }
}

impl From<FrDate> for NaiveDate {
    // frdate -> gregorian date conversion
    fn from(d: FrDate) -> NaiveDate {
        let ordinal = d.ordinal();
        let year = if ordinal < YEAR_FLIP_DAY {
            1792 + d.year - 1
        } else {
            1792 + d.year
        };
        let day = if ordinal < YEAR_FLIP_DAY {
            ordinal + 1 + if is_leap(year) { SEPT_22 } else { SEPT_21 }
        } else {
            ordinal + 1 - YEAR_FLIP_DAY
        };
        NaiveDate::from_yo_opt(year, day).unwrap()
    }
}

impl FrDate {
    /// month and day are starting from 0.
    /// If you pass to big values None is returned.
    pub fn new(year: i32, month: u32, day: u32) -> Option<FrDate> {
        if month > 12 || day > 29 {
            return None;
        }
        Some(FrDate { year, month, day })
    }

    pub fn month_name_u32(month: u32) -> &'static str {
        match month {
            0 => "Vendémiaire",
            1 => "Brumaire",
            2 => "Frimaire",
            3 => "Nivôse",
            4 => "Pluviôse",
            5 => "Ventôse",
            6 => "Germinal",
            7 => "Floréal",
            8 => "Prairial",
            9 => "Messidor",
            10 => "Thermidor",
            11 => "Fructidor",
            12 => "Sansculottides",
            _ => "Invalid Month",
        }
    }
    pub fn month_name_short_u32(month: u32) -> &'static str {
        match month {
            0 => "Vend",
            1 => "Bru",
            2 => "Fri",
            3 => "Niv",
            4 => "Plu",
            5 => "Vent",
            6 => "Germ",
            7 => "Flo",
            8 => "Pra",
            9 => "Mess",
            10 => "The",
            11 => "Fru",
            12 => "Sans",
            _ => "ERR_M",
        }
    }

    pub fn month_name(&self) -> &'static str {
        FrDate::month_name_u32(self.month)
    }
    pub fn month_name_short(&self) -> &'static str {
        FrDate::month_name_short_u32(self.month)
    }

    pub fn day_of_week_name_u32(d: u32) -> &'static str {
        match d {
            0 => "Primidi",
            1 => "Duodi",
            2 => "Tridi",
            3 => "Quartidi",
            4 => "Quintidi",
            5 => "Sextidi",
            6 => "Septidi",
            7 => "Octidi",
            8 => "Nonidi",
            9 => "Décadi",
            _ => "Invalid day",
        }
    }

    pub fn day_of_week_name_short_u32(d: u32) -> &'static str {
        match d {
            0 => "Pri",
            1 => "Duo",
            2 => "Tri",
            3 => "Qua",
            4 => "Qui",
            5 => "Sex",
            6 => "Sep",
            7 => "Oct",
            8 => "Non",
            9 => "Déc",
            _ => "ERR",
        }
    }

    pub fn day_of_week(&self) -> u32 {
        self.day % 10
    }
    pub fn day_of_week_name(&self) -> &'static str {
        FrDate::day_of_week_name_u32(self.day_of_week())
    }
    pub fn day_of_week_name_short(&self) -> &'static str {
        FrDate::day_of_week_name_short_u32(self.day_of_week())
    }

    /// day of the year (0-365), starts at 0
    pub fn ordinal(&self) -> u32 {
        (self.month * 30) + self.day
    }

    pub fn day_name(&self) -> DayName {
        FrDate::day_name_ordinal(self.ordinal())
    }

    pub fn day_name_ordinal(day_ordinal: u32) -> DayName {
        match day_ordinal {
            0 => ("Raisin", ("Grape", "Grape")),
            1 => ("Safran", ("Saffron", "Saffron")),
            2 => ("Châtaigne", ("Chestnut", "Chestnut")),
            3 => ("Colchique", ("Colchicum autumnale", "Autumn Crocus")),
            4 => ("Cheval", ("Horse", "Horse")),
            5 => ("Balsamine", ("Impatiens", "Impatiens")),
            6 => ("Carotte", ("Carrot", "Carrot")),
            7 => ("Amaranthe", ("Amaranth", "Amaranth")),
            8 => ("Panais", ("Parsnip", "Parsnip")),
            9 => ("Cuve", ("Storage tank", "Vat")),
            10 => ("Pomme de terre", ("Potato", "Potato")),
            11 => ("Immortelle", ("Helichrysum arenarium", "Strawflower")),
            12 => ("Potiron", ("Winter squash", "Winter squash")),
            13 => ("Réséda", ("Reseda (plant)", "Mignonette")),
            14 => ("Âne", ("Donkey", "Donkey")),
            15 => ("Belle de nuit", ("Mirabilis jalapa", "Four o'clock flower")),
            16 => ("Citrouille", ("Pumpkin", "Pumpkin")),
            17 => ("Sarrasin", ("Buckwheat", "Buckwheat")),
            18 => ("Tournesol", ("Helianthus", "Sunflower")),
            19 => ("Pressoir", ("Fruit press", "Wine-Press")),
            20 => ("Chanvre", ("Hemp", "Hemp")),
            21 => ("Pêche", ("Peach", "Peach")),
            22 => ("Navet", ("Turnip", "Turnip")),
            23 => ("Amaryllis", ("Amaryllis", "Amaryllis")),
            24 => ("Bœuf", ("Cattle", "Ox")),
            25 => ("Aubergine", ("Eggplant", "Eggplant")),
            26 => ("Piment", ("Chili pepper", "Chili pepper")),
            27 => ("Tomate", ("Tomato", "Tomato")),
            28 => ("Orge", ("Barley", "Barley")),
            29 => ("Tonneau", ("Barrel#Beverage maturing", "Barrel")),

            30 => ("Pomme", ("Apple", "Apple")),
            31 => ("Céleri", ("Celery", "Celery")),
            32 => ("Poire", ("Pear", "Pear")),
            33 => ("Betterave", ("Beetroot", "Beetroot")),
            34 => ("Oie", ("Goose", "Goose")),
            35 => ("Héliotrope", ("Heliotropium", "Heliotrope")),
            36 => ("Figue", ("Common fig", "Common fig")),
            37 => ("Scorsonère", ("Scorzonera hispanica", "Black Salsify")),
            38 => ("Alisier", ("Sorbus torminalis", "Chequer Tree")),
            39 => ("Charrue", ("Plough", "Plough")),
            40 => ("Salsifis", ("Tragopogon porrifolius", "Salsify")),
            41 => ("Mâcre", ("Water caltrop", "Water caltrop")),
            42 => (
                "Topinambour",
                ("Jerusalem artichoke", "Jerusalem artichoke"),
            ),
            43 => ("Endive", ("Endive", "Endive")),
            44 => ("Dindon", ("Turkey (bird)", "Turkey")),
            45 => ("Chervis", ("Sium sisarum", "Skirret")),
            46 => ("Cresson", ("Watercress", "Watercress")),
            47 => ("Dentelaire", ("Plumbaginaceae", "Leadworts")),
            48 => ("Grenade", ("Pomegranate", "Pomegranate")),
            49 => ("Herse", ("Harrow (tool)", "Harrow")),
            50 => ("Bacchante", ("Baccharis halimifolia", "Baccharis")),
            51 => ("Azerole", ("Crataegus azarolus", "Azarole")),
            52 => ("Garance", ("Rubia", "Madder")),
            53 => ("Orange", ("Orange (fruit)", "Orange")),
            54 => ("Faisan", ("Pheasant", "Pheasant")),
            55 => ("Pistache", ("Pistachio", "Pistachio Nut")),
            56 => ("Macjonc", ("Lathyrus tuberosus", "Tuberous pea")),
            57 => ("Coing", ("Quince", "Quince")),
            58 => ("Cormier", ("Sorbus domestica", "Service tree")),
            59 => ("Rouleau", ("Roller (agricultural tool)", "Roller")),

            60 => ("Raiponce", ("Phyteuma", "Rampion")),
            61 => ("Turneps", ("Turnip", "Cattle turnip")),
            62 => ("Chicorée", ("Chicory", "Chicory")),
            63 => ("Nèfle", ("Mespilus germanica", "Medlar")),
            64 => ("Cochon", ("Pig", "Pig")),
            65 => ("Mâche", ("Valerianella locusta", "Lamb's lettuce")),
            66 => ("Chou-fleur", ("Cauliflower", "Cauliflower")),
            67 => ("Miel", ("Honey", "Honey")),
            68 => ("Genièvre", ("Juniperus communis", "Juniper")),
            69 => ("Pioche", ("Pickaxe", "Pickaxe")),
            70 => ("Cire", ("Wax", "Wax")),
            71 => ("Raifort", ("Horseradish", "Horseradish")),
            72 => ("Cèdre", ("Cedrus", "Cedar tree")),
            73 => ("Sapin", ("Fir", "Fir")),
            74 => ("Chevreuil", ("Roe deer", "Roe deer")),
            75 => ("Ajonc", ("Ulex", "Gorse")),
            76 => ("Cyprès", ("Cupressus sempervirens", "Cypress Tree")),
            77 => ("Lierre", ("Hedera", "Ivy")),
            78 => ("Sabine", ("Juniperus sabina", "Savin Juniper")),
            79 => ("Hoyau", ("Hoe (tool)", "Grub-hoe")),
            80 => ("Érable à sucre", ("Acer saccharum", "Sugar Maple")),
            81 => ("Bruyère", ("Calluna", "Heather")),
            82 => ("Roseau", ("Phragmites", "Reed plant")),
            83 => ("Oseille", ("Sorrel", "Sorrel")),
            84 => ("Grillon", ("Cricket (insect)", "Cricket")),
            85 => ("Pignon", ("Pine nut", "Pine nut")),
            86 => ("Liège", ("Cork (material)", "Cork")),
            87 => ("Truffe", ("Truffle", "Truffle")),
            88 => ("Olive", ("Olive", "Olive")),
            89 => ("Pelle", ("Shovel", "Shovel")),

            90 => ("Tourbe", ("Peat", "Peat")),
            91 => ("Houille", ("Coal", "Coal")),
            92 => ("Bitume", ("Bitumen", "Bitumen")),
            93 => ("Soufre", ("Sulphur", "Sulphur")),
            94 => ("Chien", ("Dog", "Dog")),
            95 => ("Lave", ("Lava", "Lava")),
            96 => ("Terre végétale", ("Topsoil", "Topsoil")),
            97 => ("Fumier", ("Manure", "Manure")),
            98 => ("Salpêtre", ("Potassium nitrate", "Saltpeter")),
            99 => ("Fléau", ("Flail (agriculture)", "Flail")),
            100 => ("Granit", ("Granite", "Granite")),
            101 => ("Argile", ("Clay", "Clay")),
            102 => ("Ardoise", ("Slate", "Slate")),
            103 => ("Grès", ("Sandstone", "Sandstone")),
            104 => ("Lapin", ("Rabbit", "Rabbit")),
            105 => ("Silex", ("Flint", "Flint")),
            106 => ("Marne", ("Marl", "Marl")),
            107 => ("Pierre à chaux", ("Limestone", "Limestone")),
            108 => ("Marbre", ("Marble", "Marble")),
            109 => ("Van", ("Winnowing", "Winnowing fan")),
            110 => ("Pierre à plâtre", ("Gypsum", "Gypsum")),
            111 => ("Sel", ("Salt", "Salt")),
            112 => ("Fer", ("Iron (material)", "Iron")),
            113 => ("Cuivre", ("Copper", "Copper")),
            114 => ("Chat", ("Cat", "Cat")),
            115 => ("Étain", ("Tin", "Tin")),
            116 => ("Plomb", ("Lead", "Lead")),
            117 => ("Zinc", ("Zinc", "Zinc")),
            118 => ("Mercure", ("Mercury (element)", "Mercury")),
            119 => ("Crible", ("Sieve", "Sieve")),
            120 => ("Lauréole", ("Daphne laureola", "Spurge-laurel")),
            121 => ("Mousse", ("Moss", "Moss")),
            122 => ("Fragon", ("Ruscus aculeatus", "Butcher's Broom")),
            123 => ("Perce-neige", ("Snowdrop", "Snowdrop")),
            124 => ("Taureau", ("Cattle", "Bull")),
            125 => ("Laurier-thym", ("Viburnum tinus", "Laurustinus")),
            126 => ("Amadouvier", ("Fomes fomentarius", "Tinder polypore")),
            127 => ("Mézéréon", ("Daphne mezereum", "Daphne mezereum")),
            128 => ("Peuplier", ("Populus", "Poplar")),
            129 => ("Coignée", ("Axe", "Axe")),
            130 => ("Ellébore", ("Hellebore", "Hellebore")),
            131 => ("Brocoli", ("Broccoli", "Broccoli")),
            132 => ("Laurier", ("Bay laurel", "Bay laurel")),
            133 => ("Avelinier", ("Corylus maxima", "Filbert")),
            134 => ("Vache", ("Cattle", "Cow")),
            135 => ("Buis", ("Box (tree)", "Box Tree")),
            136 => ("Lichen", ("Lichen", "Lichen")),
            137 => ("If", ("Taxus baccata", "Yew tree")),
            138 => ("Pulmonaire", ("Lungwort", "Lungwort")),
            139 => ("Serpette", ("Billhook", "Billhook")),
            140 => ("Thlaspi", ("Thlaspi arvense", "Pennycress")),
            141 => ("Thimelé", ("Daphne cneorum", "Rose Daphne")),
            142 => ("Chiendent", ("Elymus repens", "Couch grass")),
            143 => ("Trainasse", ("Polygonum aviculare", "Common Knotgrass")),
            144 => ("Lièvre", ("Hare", "Hare")),
            145 => ("Guède", ("Woad", "Woad")),
            146 => ("Noisetier", ("Hazel", "Hazel")),
            147 => ("Cyclamen", ("Cyclamen", "Cyclamen")),
            148 => ("Chélidoine", ("Greater celandine", "Celandine")),
            149 => ("Traîneau", ("Sleigh", "Sleigh")),

            150 => ("Tussilage", ("Tussilago", "Coltsfoot")),
            151 => ("Cornouiller", ("Cornus (genus)", "Dogwood")),
            152 => ("Violier", ("Matthiola", "Matthiola")),
            153 => ("Troène", ("Privet", "Privet")),
            154 => ("Bouc", ("Goat", "Billygoat")),
            155 => ("Asaret", ("Asarum", "Wild Ginger")),
            156 => ("Alaterne", ("Rhamnus alaternus", "Italian Buckthorn")),
            157 => ("Violette", ("Viola (plant)", "Violet")),
            158 => ("Marceau", ("Salix caprea", "Goat Willow")),
            159 => ("Bêche", ("Spade", "Spade")),
            160 => ("Narcisse", ("Narcissus (plant)", "Narcissus")),
            161 => ("Orme", ("Elm", "Elm")),
            162 => ("Fumeterre", ("Fumaria officinalis", "Common fumitory")),
            163 => ("Vélar", ("Sisymbrium officinale", "Hedge mustard")),
            164 => ("Chèvre", ("Goat", "Goat")),
            165 => ("Épinard", ("Spinach", "Spinach")),
            166 => ("Doronic", ("Doronicum", "Doronicum")),
            167 => ("Mouron", ("Anagallis", "Pimpernel")),
            168 => ("Cerfeuil", ("Chervil", "Chervil")),
            169 => ("Cordeau", ("Twine", "Twine")),
            170 => ("Mandragore", ("Mandragora officinarum", "Mandrake")),
            171 => ("Persil", ("Parsley", "Parsley")),
            172 => ("Cochléaria", ("Cochlearia", "Scurvy-grass")),
            173 => ("Pâquerette", ("Bellis perennis", "Daisy")),
            174 => ("Thon", ("Tuna", "Tuna")),
            175 => ("Pissenlit", ("Taraxacum", "Dandelion")),
            176 => ("Sylvie", ("Anemone nemorosa", "Wood Anemone")),
            177 => (
                "Capillaire",
                ("Adiantum capillus-veneris", "Maidenhair fern"),
            ),
            178 => ("Frêne", ("Fraxinus", "Ash tree")),
            179 => ("Plantoir", ("Dibber", "Dibber")),

            180 => ("Primevère", ("Primula vulgaris", "Primrose")),
            181 => ("Platane", ("Platanus", "Plane Tree")),
            182 => ("Asperge", ("Asparagus", "Asparagus")),
            183 => ("Tulipe", ("Tulip", "Tulip")),
            184 => ("Poule", ("Chicken", "Hen")),
            185 => ("Bette", ("Chard", "Chard")),
            186 => ("Bouleau", ("Birch", "Birch")),
            187 => ("Jonquille", ("Narcissus (plant)", "Daffodil")),
            188 => ("Aulne", ("Alder", "Alder")),
            189 => ("Couvoir", ("Hatchery", "Hatchery")),
            190 => ("Pervenche", ("Vinca", "Periwinkle")),
            191 => ("Charme", ("Hornbeam", "Hornbeam")),
            192 => ("Morille", ("Morchella", "Morel")),
            193 => ("Hêtre", ("Fagus sylvatica", "Beech Tree")),
            194 => ("Abeille", ("Bee", "Bee")),
            195 => ("Laitue", ("Lettuce", "Lettuce")),
            196 => ("Mélèze", ("Larch", "Larch")),
            197 => ("Ciguë", ("Conium", "Hemlock")),
            198 => ("Radis", ("Radish", "Radish")),
            199 => ("Ruche", ("Beehive (beekeeping)", "Hive")),
            200 => ("Gainier", ("Cercis", "Judas tree")),
            201 => ("Romaine", ("Romaine lettuce", "Romaine lettuce")),
            202 => ("Marronnier", ("Aesculus hippocastanum", "Horse chestnut")),
            203 => ("Roquette", ("Arugula", "Arugula or Rocket")),
            204 => ("Pigeon", ("Pigeon", "Pigeon")),
            205 => ("Lilas", ("Lilac", "Lilac")),
            206 => ("Anémone", ("Anemone nemorosa", "Anemone")),
            207 => ("Pensée", ("Pansy", "Pansy")),
            208 => ("Myrtille", ("Bilberry", "Bilberry")),
            209 => ("Greffoir", ("Grafter", "Grafting knife")),

            210 => ("Rose", ("Rose", "Rose")),
            211 => ("Chêne", ("Quercus robur", "Oak Tree")),
            212 => ("Fougère", ("Fern", "Fern")),
            213 => ("Aubépine", ("Crataegus", "Hawthorn")),
            214 => ("Rossignol", ("Nightingale", "Nightingale")),
            215 => ("Ancolie", ("Aquilegia vulgaris", "Common Columbine")),
            216 => ("Muguet", ("Lily of the valley", "Lily of the valley")),
            217 => ("Champignon", ("Agaricus bisporus", "Button mushroom")),
            218 => ("Hyacinthe", ("Hyacinth (plant)", "Hyacinth")),
            219 => ("Râteau", ("Rake (tool)", "Rake")),
            220 => ("Rhubarbe", ("Rhubarb", "Rhubarb")),
            221 => ("Sainfoin", ("Sainfoin", "Sainfoin")),
            222 => ("Bâton d'or", ("Erysimum", "Wallflower")),
            223 => ("Chamerisier", ("Chamaerops", "Fan Palm tree")),
            224 => ("Ver à soie", ("Silkworm", "Silkworm")),
            225 => ("Consoude", ("Comfrey", "Comfrey")),
            226 => ("Pimprenelle", ("Salad burnet", "Salad burnet")),
            227 => ("Corbeille d'or", ("Aurinia saxatilis", "Basket of Gold")),
            228 => ("Arroche", ("Orache", "Orache")),
            229 => ("Sarcloir", ("Hoe (tool)", "Garden hoe")),
            230 => ("Statice", ("Armeria maritima", "Thrift")),
            231 => ("Fritillaire", ("Fritillaria", "Fritillary")),
            232 => ("Bourrache", ("Borage", "Borage")),
            233 => ("Valériane", ("Valerian (plant)", "Valerian")),
            234 => ("Carpe", ("Carp", "Carp")),
            235 => ("Fusain", ("Euonymus", "Spindle (shrub)")),
            236 => ("Civette", ("Chive", "Chive")),
            237 => ("Buglosse", ("Anchusa", "Bugloss")),
            238 => ("Sénevé", ("Mustard plant", "Wild mustard")),
            239 => ("Houlette", ("Shepherd's crook", "Shepherd's crook")),

            240 => ("Luzerne", ("Alfalfa", "Alfalfa")),
            241 => ("Hémérocalle", ("Daylily", "Daylily")),
            242 => ("Trèfle", ("Clover", "Clover")),
            243 => ("Angélique", ("Garden Angelica", "Angelica")),
            244 => ("Canard", ("Duck", "Duck")),
            245 => ("Mélisse", ("Lemon balm", "Lemon balm")),
            246 => ("Fromental", ("Arrhenatherum", "Oat grass")),
            247 => ("Martagon", ("Lilium martagon", "Martagon lily")),
            248 => ("Serpolet", ("Thymus serpyllum", "Wild Thyme")),
            249 => ("Faux", ("Scythe", "Scythe")),
            250 => ("Fraise", ("Strawberry", "Strawberry")),
            251 => ("Bétoine", ("Stachys officinalis", "Woundwort")),
            252 => ("Pois", ("Pea", "Pea")),
            253 => ("Acacia", ("Acacia", "Acacia")),
            254 => ("Caille", ("Quail", "Quail")),
            255 => ("Œillet", ("Dianthus caryophyllus", "Carnation")),
            256 => ("Sureau", ("Elderberry", "Elderberry")),
            257 => ("Pavot", ("Papaver rhoeas", "Poppy plant")),
            258 => ("Tilleul", ("Tilia cordata", "Linden or Lime tree")),
            259 => ("Fourche", ("Pitchfork", "Pitchfork")),
            260 => ("Barbeau", ("Cornflower", "Cornflower")),
            261 => ("Camomille", ("Camomile", "Camomile")),
            262 => ("Chèvrefeuille", ("Honeysuckle", "Honeysuckle")),
            263 => ("Caille-lait", ("Galium album", "Bedstraw")),
            264 => ("Tanche", ("Tench", "Tench")),
            265 => ("Jasmin", ("Jasmine", "Jasmine")),
            266 => ("Verveine", ("Verbena officinalis", "Verbena")),
            267 => ("Thym", ("Thyme", "Thyme")),
            268 => ("Pivoine", ("Peony", "Peony")),
            269 => ("Chariot", ("Handcart", "Hand Cart")),

            270 => ("Seigle", ("Rye", "Rye")),
            271 => ("Avoine", ("Oat", "Oat")),
            272 => ("Oignon", ("Onion", "Onion")),
            273 => ("Véronique", ("Veronica (plant)", "Speedwell")),
            274 => ("Mulet", ("Mule", "Mule")),
            275 => ("Romarin", ("Rosemary", "Rosemary")),
            276 => ("Concombre", ("Cucumber", "Cucumber")),
            277 => ("Échalote", ("Shallot", "Shallot")),
            278 => ("Absinthe", ("Artemisia absinthium", "Wormwood")),
            279 => ("Faucille", ("Sickle", "Sickle")),
            280 => ("Coriandre", ("Coriander", "Coriander")),
            281 => ("Artichaut", ("Globe artichoke", "Artichoke")),
            282 => ("Girofle", ("Clove", "Clove")),
            283 => ("Lavande", ("Lavender", "Lavender")),
            284 => ("Chamois", ("Chamois", "Chamois")),
            285 => ("Tabac", ("Tobacco", "Tobacco")),
            286 => ("Groseille", ("Redcurrant", "Redcurrant")),
            287 => ("Gesse", ("Lathyrus", "Hairy Vetchling")),
            288 => ("Cerise", ("Cherry", "Cherry")),
            289 => ("Parc", ("Park", "Park")),
            290 => ("Menthe", ("Mentha", "Mint")),
            291 => ("Cumin", ("Cumin", "Cumin")),
            292 => ("Haricot", ("Bean", "Bean")),
            293 => ("Orcanète", ("Alcanna tinctoria", "Alkanet")),
            294 => ("Pintade", ("Guineafowl", "Guineafowl")),
            295 => ("Sauge", ("Salvia officinalis", "Sage")),
            296 => ("Ail", ("Garlic", "Garlic")),
            297 => ("Vesce", ("Vicia sativa", "Tare")),
            298 => ("Blé", ("Wheat", "Wheat")),
            299 => ("Chalémie", ("Shawm", "Shawm")),

            300 => ("Épeautre", ("Spelt", "Spelt")),
            301 => ("Bouillon blanc", ("Common mullein", "Common mullein")),
            302 => ("Melon", ("Muskmelon", "Melon")),
            303 => ("Ivraie", ("Ryegrass", "Ryegrass")),
            304 => ("Bélier", ("Sheep", "Ram")),
            305 => ("Prêle", ("Equisetum", "Horsetail")),
            306 => ("Armoise", ("Artemisia vulgaris", "Mugwort")),
            307 => ("Carthame", ("Safflower", "Safflower")),
            308 => ("Mûre", ("Blackberry", "Blackberry")),
            309 => ("Arrosoir", ("Watering can", "Watering can")),
            310 => ("Panic", ("Panicum italicum", "Foxtail millet")),
            311 => ("Salicorne", ("Glasswort", "Common Glasswort")),
            312 => ("Abricot", ("Apricot", "Apricot")),
            313 => ("Basilic", ("Basil", "Basil")),
            314 => ("Brebis", ("Sheep", "Ewe")),
            315 => ("Guimauve", ("Althaea officinalis", "Marshmallow")),
            316 => ("Lin", ("Flax", "Flax")),
            317 => ("Amande", ("Almond", "Almond")),
            318 => ("Gentiane", ("Gentian", "Gentian")),
            319 => ("Écluse", ("Lock (water transport)", "Lock")),
            320 => ("Carline", ("Carline thistle", "Carline thistle")),
            321 => ("Câprier", ("Caper", "Caper")),
            322 => ("Lentille", ("Lentil", "Lentil")),
            323 => ("Aunée", ("Inula", "Inula")),
            324 => ("Loutre", ("Otter", "Otter")),
            325 => ("Myrte", ("Myrtus", "Myrtle")),
            326 => ("Colza", ("Rapeseed", "Rapeseed")),
            327 => ("Lupin", ("Lupin", "Lupin")),
            328 => ("Coton", ("Cotton", "Cotton")),
            329 => ("Moulin", ("Windmill", "Mill")),

            330 => ("Prune", ("Plum", "Plum")),
            331 => ("Millet", ("Millet", "Millet")),
            332 => ("Lycoperdon", ("Puffball", "Puffball")),
            333 => ("Escourgeon", ("Barley", "Six-row Barley")),
            334 => ("Saumon", ("Salmon", "Salmon")),
            335 => ("Tubéreuse", ("Tuberose", "Tuberose")),
            336 => ("Sucrion", ("Barley", "Winter Barley")),
            337 => ("Apocyn", ("Apocynaceae", "Apocynum")),
            338 => ("Réglisse", ("Liquorice", "Liquorice")),
            339 => ("Échelle", ("Ladder", "Ladder")),
            340 => ("Pastèque", ("Watermelon", "Watermelon")),
            341 => ("Fenouil", ("Fennel", "Fennel")),
            342 => ("Épine vinette", ("Berberis vulgaris", "European Barberry")),
            343 => ("Noix", ("Walnut", "Walnut")),
            344 => ("Truite", ("Trout", "Trout")),
            345 => ("Citron", ("Lemon", "Lemon")),
            346 => ("Cardère", ("Dipsacus", "Teasel")),
            347 => ("Nerprun", ("Buckthorn", "Buckthorn")),
            348 => ("Tagette", ("Tagetes", "Mexican Marigold")),
            349 => ("Hotte", ("Basket", "Harvesting basket")),
            350 => ("Églantier", ("Rosa canina", "Wild Rose")),
            351 => ("Noisette", ("Hazelnut", "Hazelnut")),
            352 => ("Houblon", ("Humulus lupulus", "Hops")),
            353 => ("Sorgho", ("Sorghum", "Sorghum")),
            354 => ("Écrevisse", ("Crayfish", "Crayfish")),
            355 => ("Bigarade", ("Bitter orange", "Bitter orange")),
            356 => ("Verge d'or", ("Goldenrod", "Goldenrod")),
            357 => ("Maïs", ("Maize", "Maize or Corn")),
            358 => ("Marron", ("Sweet Chestnut", "Sweet Chestnut")),
            359 => ("Panier", ("Basket", "Pack Basket")),

            360 => (
                "La Fête de la Vertu",
                ("La Fête de la Vertu", "La Fête de la Vertu"),
            ),
            361 => ("La Fête du Génie", ("La Fête du Génie", "La Fête du Génie")),
            362 => (
                "La Fête du Travail",
                ("La Fête du Travail", "La Fête du Travail"),
            ),
            363 => (
                "La Fête de l'Opinion",
                ("La Fête de l'Opinion", "La Fête de l'Opinion"),
            ),
            364 => (
                "La Fête des Récompenses",
                ("La Fête des Récompenses", "La Fête des Récompenses"),
            ),
            365 => (
                "La Fête de la Révolution",
                ("La Fête de la Révolution", "La Fête de la Révolution"),
            ),
            _ => ("Invalid Day", ("", "")),
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn from() {
        // let date = NaiveDate::from_ymd_opt(2023,10,19).unwrap();
        // assert_eq!(FrDate {year: 232, month:0, day:27}, date.into());

        let date = NaiveDate::from_ymd_opt(2023, 1, 1).unwrap();
        assert_eq!(1, date.ordinal());

        let date = NaiveDate::from_ymd_opt(2023, 1, 1).unwrap();
        assert_eq!(
            FrDate {
                year: 231,
                month: 3,
                day: 11
            },
            date.into()
        );

        let date = NaiveDate::from_ymd_opt(2023, 10, 18).unwrap();
        assert_eq!(
            FrDate {
                year: 232,
                month: 0,
                day: 26
            },
            date.into()
        );

        let date = NaiveDate::from_ymd_opt(2023, 9, 22).unwrap();
        assert_eq!(
            FrDate {
                year: 232,
                month: 0,
                day: 0
            },
            date.into()
        );

        let date = NaiveDate::from_ymd_opt(2023, 9, 17).unwrap();
        assert_eq!(
            FrDate {
                year: 231,
                month: 12,
                day: 0
            },
            date.into()
        );

        let date = NaiveDate::from_ymd_opt(2023, 9, 21).unwrap();
        assert_eq!(
            FrDate {
                year: 231,
                month: 12,
                day: 4
            },
            date.into()
        );

        // leap
        let date = NaiveDate::from_ymd_opt(2024, 9, 21).unwrap();
        assert_eq!(
            FrDate {
                year: 232,
                month: 12,
                day: 5
            },
            date.into()
        );

        for y in 1970..2051 {
            for i in 1..366 {
                let date = NaiveDate::from_yo_opt(y, i).unwrap();
                let fr: FrDate = date.into();
                let back: NaiveDate = fr.into();
                println!("{y}-{i}");
                assert_eq!(back, date);
            }
        }
    }
}