Integrate Nepali Calender to all default date field in ERPNext

Hello @everyone, I tried integrating nepali calender, diplaying and setting nepali date to UI i.e in the client side. I tried overriding frappe controlDate calss of date.js (frappe/frappe/public/js/frappe/form/controls/date.js at version-15 · frappe/frappe · GitHub). It has been successfully overriden and nepali calender is showing well the issue is when any doctype is getting submitted it is changing back to AD date in the UI. The goal is to send AD to frappe model so that everything work as per erpnext default but in the UI it should be always nepali date. override_date.js code is

frappe.ui.form.ControlDate = class CustomNepaliDate extends frappe.ui.form.ControlData {
    make() {
        super.make();
        this._is_setting_value = false; // Flag to prevent infinite loops
        this.setup_nepali_date_picker();
    }

    make_input() {
        super.make_input();
        this.setup_nepali_date_picker();
    }

    setup_nepali_date_picker() {
        // Clean up existing datepickers
        if (this.datepicker) {
            this.datepicker.destroy();
            this.datepicker = null;
        }
        this.$wrapper.find(".datepicker-icon").remove();
        this.$input.attr("type", "text");

        // Initialize Nepali Date Picker
        this.$input.nepaliDatePicker({
            ndpYear: true,
            ndpMonth: true,
            ndpYearCount: 100,
            ndpFormat: 'YYYY-MM-DD',
            closeOnDateSelect: true,
            onChange: (e) => {
                if (this._is_setting_value) return;
                
                const bs_date = e.bs;
                try {
                    const ad_date = NepaliFunctions.BS2AD(bs_date);
                    this._is_setting_value = true;
                    this.set_value(ad_date); // This will trigger set_formatted_input
                    this._is_setting_value = false;
                } catch (error) {
                    console.error("Date conversion failed:", error);
                }
            }
        });

        // Initialize with BS date if value exists
        if (this.value) {
            this.set_formatted_input(this.value);
        }
    }

    set_formatted_input(value) {
        if (!value) {
            this.$input && this.$input.val("");
            return;
        }

        try {
            const bs_date = NepaliFunctions.AD2BS(value);
            this.$input && this.$input.val(bs_date);
        } catch (error) {
            console.error("Date display conversion failed:", error);
            this.$input && this.$input.val(value);
        }
    }

    set_value(value) {
        // Store the actual AD value
        super.set_value(value);
        // Update display with BS date
        this.set_formatted_input(value);
    }

    parse(value) {
        if (!value || value === '') return '';
        
        if (value === "Today") {
            return NepaliFunctions.BS2AD(NepaliFunctions.getToday());
        }
        
        try {
            // If it's already in AD format (YYYY-MM-DD)
            if (/^\d{4}-\d{2}-\d{2}$/.test(value)) {
                return value;
            }
            // If it's in BS format, convert to AD
            return NepaliFunctions.BS2AD(value);
        } catch (error) {
            console.error("Date parsing failed:", error);
            return value;
        }
    }
};

Note: NepaliFunctions.BS2AD and NepaliFunctions.AD2BS is available in the nepali_library.js that hepls in converting eqivalent Nepali Date to AD Date and vice versa.

hooks.py is

app_include_css = ["/assets/nepali_calendar/css/nepali_calendar.css"]
app_include_js = [
                 "/assets/nepali_calendar/js/nepali_library.js",
                 "assets/nepali_calendar/js/override.js",
                 ]

I look forward from frappe community and all the member here in the forum to give some insight. What is lagging or missing in the code and how Frappe handle this and works in ERPNext. Thank You

I guess you can find apps on the frappecloud marketplace.

There’s an open source one (MIT licensed) as well -