You are currently viewing Calendar with Reactjs Typescript using Moment

Calendar with Reactjs Typescript using Moment

Instructions for writing logic: return results as shown:

  • List of dates, previous month, next month and next month: item returned with date type, current date
  • Current date details
image.png
  1. Create Context API – to share data
'use client';

import { PropsWithChildren, createContext, useContext } from 'react';
import useLogic from './hook';

type Extra = {};

type ValueCtx = ReturnType<typeof useLogic> & Extra;

export const CalendarCtx = createContext({} as ValueCtx);

export const CalendarProvider = ({ ...props }: PropsWithChildren<Extra>) => {
    const valueCtx = useLogic();
    return (
        <CalendarCtx.Provider value={{ ...valueCtx, ...props }}>
            <>{props.children}</>
        </CalendarCtx.Provider>
    );
};

export const useCalendarCtx = () => useContext(CalendarCtx);

  1. Create Hook – to handle logic
'use client';

import moment from 'moment';
import { useState } from 'react';
import { calcDays, dataDate } from './data';
import { onSolar2Lunar } from './lunar';

const useLogic = () => {
    const [date, setDate] = useState(moment());

    const handleReload = () => {
        setDate(moment());
    };

    const handlePrev = () => {
        setDate((element: any) => moment(element).subtract(1, 'month'));
    };

    const handleNext = () => {
        setDate((element: any) => moment(element).add(1, 'month'));
    };

    const currentLunar = () => {
        const curdate = dataDate({ date: moment() });
        const solar = onSolar2Lunar(
            curdate.day,
            curdate.curMonth,
            curdate.year
        );

        return solar;
    };

    return {
        date,
        setDate,
        listDay: calcDays({ ...dataDate({ date }) }),
        current: dataDate({ date }),
        handlePrev,
        handleNext,
        handleReload,
        currentLunar,
    };
};

export default useLogic;

  1. Method: Process dates

import { range } from 'lodash';
import moment, { Moment } from 'moment';
import 'moment/locale/vi';
import { onSolar2Lunar } from './lunar';
import { CalcDays, ItemDay } from './types';

enum DefineDays {
    DaysOut = 'DaysOut',
    DaysIn = 'DaysIn',
}

export type DataDate = { date: Moment };

export const dataDate = ({ date }: DataDate) => {
    const day = date.date();
    const year = date.year(); // lấy năm hiện tại
    const month = date.month(); // lấy tháng hiện tại

    const daysInMonth = date.daysInMonth(); // lấy số ngày trong tháng , ví dụ như 30 ngày

    const dayOfMonth = moment(date).subtract(1, 'months'); // lấy tháng vừa rồi
    const dayOf = moment(`${year}-${month + 1}-1`); // tuần đầu tiền của tháng

    const weekDayOf = dayOf.day(); // số ngày củ cua tháng rồi

    const dayNew = moment(`${year}-${month + 1}-${daysInMonth}`); // tuần cuối cùng của tháng

    const weekDayNew = dayNew.day(); // sô ngày mới của tháng tới

    return {
        day,
        year,
        month,
        curMonth: month + 1,
        daysInMonth,
        dayOfMonth,
        weekDayOf,
        weekDayNew,
        dayNew,
    };
};

export const calcDays = ({
    weekDayOf,
    dayOfMonth,
    weekDayNew,
    daysInMonth,
    dayNew,
    year,
    month,
}: CalcDays) => {
    // lịch việt thì weekDayOf - 1 ,  weekDayOf + 1 ,
    // lịch Quốc tế thì weekDayOf , weekDayOf + 1
    const daysOld: ItemDay[] = range(weekDayOf - 1).map((item) => {
        const iday = dayOfMonth.daysInMonth() - weekDayOf + 1 + item + 1;
        return {
            daysLunar: onSolar2Lunar(iday, month, year),
            days: iday,
            type: DefineDays.DaysOut,
            daysSolar: {
                day: iday,
                month,
                year,
                ddmm: `${iday}/${month}`,
                ddmmyyyy: `${iday}/${month}/${year}`,
            },
        };
    });

    const days: ItemDay[] = range(daysInMonth).map((item) => {
        const isToday = moment(`${item + 1}/${month + 1}/${year}`).isSame(
            moment(),
            'day'
        );

        return {
            daysLunar: onSolar2Lunar(item + 1, month + 1, year),
            days: item + 1,
            type: DefineDays.DaysIn,
            isToday,
            daysSolar: {
                day: item + 1,
                month: month + 1,
                year,
                ddmm: `${item + 1}/${month + 1}`,
                ddmmyyyy: `${item + 1}/${month + 1}/${year}`,
            } as const,
        };
    });

    const daysNew: ItemDay[] = range(6 + 1 - weekDayNew).map(() => {
        const iday = dayNew.add(1, 'day').date();
        return {
            daysLunar: onSolar2Lunar(iday, month + 2, year),
            days: iday,
            type: DefineDays.DaysOut,
            daysSolar: {
                day: iday,
                month: month + 2,
                year,
                ddmm: `${iday}/${month + 2}`,
                ddmmyyyy: `${iday}/${month + 2}/${year}`,
            },
        };
    });

    return daysOld.concat(days, daysNew);
};

  1. Data Definition
import { Moment } from 'moment';

export type CalcDays = {
    year: number;
    month: number;
    daysInMonth: any;
    dayOfMonth: Moment;
    weekDayOf: number;
    weekDayNew: number;
    dayNew: Moment;
};

export type ItemDay = {
    daysLunar: LunarType;
    days: number;
    type: string;
    isToday?: boolean;
    daysSolar?: DaySolarType;
};

export interface LunarType {
    dd: number;
    mm: any;
    yy: number;
    ix: any;
    LLLL: string;
    DM: string;
}

export type DaySolarType = {
    day: number;
    month: number;
    year: number;
    ddmm?: string;
    ddmmyyyy?: string;
};

  1. Lunar calendar calculation: Lunar
/* eslint-disable id-length */
/* eslint-disable prefer-const */
import { chunk, range } from 'lodash';

export const LOCAL_TIMEZONE = 7.0;

export const INT = (d = 0) => {
    return Math.floor(d);
};

export const MOD = (x = 0, y = 0) => {
    let z = x - y * Math.floor(x / y);
    if (z === 0) {
        z = y;
    }
    return z;
};

export const UniversalFromJD = (JD = 0) => {
    let Z;
    let A;
    let B;
    let C;
    let D;
    let E;
    let F;
    let alpha;
    let dd;
    let mm;
    let yyyy;

    Z = INT(JD + 0.5);
    F = JD + 0.5 - Z;

    if (Z < 2299161) {
        A = Z;
    } else {
        alpha = INT((Z - 1867216.25) / 36524.25);
        A = Z + 1 + alpha - INT(alpha / 4);
    }
    B = A + 1524;
    C = INT((B - 122.1) / 365.25);
    D = INT(365.25 * C);
    E = INT((B - D) / 30.6001);
    dd = INT(B - D - INT(30.6001 * E) + F);
    if (E < 14) {
        mm = E - 1;
    } else {
        mm = E - 13;
    }
    if (mm < 3) {
        yyyy = C - 4715;
    } else {
        yyyy = C - 4716;
    }
    return { dd, mm, yyyy };
};

export const UniversalToJD = (D = 0, M = 0, Y = 0) => {
    let JD;
    if (
        Y > 1582 ||
        (Y === 1582 && M > 10) ||
        (Y === 1582 && M === 10 && D > 14)
    ) {
        JD =
            367 * Y -
            INT((7 * (Y + INT((M + 9) / 12))) / 4) -
            INT((3 * (INT((Y + (M - 9) / 7) / 100) + 1)) / 4) +
            INT((275 * M) / 9) +
            D +
            1721028.5;
    } else {
        JD =
            367 * Y -
            INT((7 * (Y + 5001 + INT((M - 9) / 7))) / 4) +
            INT((275 * M) / 9) +
            D +
            1729776.5;
    }
    return JD;
};

export const LocalFromJD = (JD = 0) => {
    return UniversalFromJD(JD + LOCAL_TIMEZONE / 24.0);
};
export const LocalToJD = (D = 0, M = 0, Y = 0) => {
    return UniversalToJD(D, M, Y) - LOCAL_TIMEZONE / 24.0;
};

export const { PI } = Math;

export const NewMoon = (k = 0) => {
    const T = k / 1236.85;
    const T2 = T * T;
    const T3 = T2 * T;
    const dr = PI / 180;
    let Jd1 =
        2415020.75933 + 29.53058868 * k + 0.0001178 * T2 - 0.000000155 * T3;
    Jd1 = Jd1 + 0.00033 * Math.sin((166.56 + 132.87 * T - 0.009173 * T2) * dr); // Mean new moon
    const M = 359.2242 + 29.10535608 * k - 0.0000333 * T2 - 0.00000347 * T3; // Sun's mean anomaly
    const Mpr = 306.0253 + 385.81691806 * k + 0.0107306 * T2 + 0.00001236 * T3; // Moon's mean anomaly
    const F = 21.2964 + 390.67050646 * k - 0.0016528 * T2 - 0.00000239 * T3; // Moon's argument of latitude
    let C1 =
        (0.1734 - 0.000393 * T) * Math.sin(M * dr) +
        0.0021 * Math.sin(2 * dr * M);
    C1 = C1 - 0.4068 * Math.sin(Mpr * dr) + 0.0161 * Math.sin(dr * 2 * Mpr);
    C1 = C1 - 0.0004 * Math.sin(dr * 3 * Mpr);
    C1 = C1 + 0.0104 * Math.sin(dr * 2 * F) - 0.0051 * Math.sin(dr * (M + Mpr));
    C1 =
        C1 -
        0.0074 * Math.sin(dr * (M - Mpr)) +
        0.0004 * Math.sin(dr * (2 * F + M));
    C1 =
        C1 -
        0.0004 * Math.sin(dr * (2 * F - M)) -
        0.0006 * Math.sin(dr * (2 * F + Mpr));
    C1 =
        C1 +
        0.001 * Math.sin(dr * (2 * F - Mpr)) +
        0.0005 * Math.sin(dr * (2 * Mpr + M));
    let deltat;
    if (T < -11) {
        deltat =
            0.001 +
            0.000839 * T +
            0.0002261 * T2 -
            0.00000845 * T3 -
            0.000000081 * T * T3;
    } else {
        deltat = -0.000278 + 0.000265 * T + 0.000262 * T2;
    }
    const JdNew = Jd1 + C1 - deltat;
    return JdNew;
};

export const SunLongitude = (jdn = 0) => {
    const T = (jdn - 2451545.0) / 36525; // Time in Julian centuries from 2000-01-01 12:00:00 GMT
    const T2 = T * T;
    const dr = PI / 180; // degree to radian
    const M = 357.5291 + 35999.0503 * T - 0.0001559 * T2 - 0.00000048 * T * T2; // mean anomaly, degree
    const L0 = 280.46645 + 36000.76983 * T + 0.0003032 * T2; // mean longitude, degree
    let DL = (1.9146 - 0.004817 * T - 0.000014 * T2) * Math.sin(dr * M);
    DL =
        DL +
        (0.019993 - 0.000101 * T) * Math.sin(dr * 2 * M) +
        0.00029 * Math.sin(dr * 3 * M);
    let L = L0 + DL; // true longitude, degree
    L = L * dr;
    L = L - PI * 2 * INT(L / (PI * 2)); // Normalize to (0, 2*PI)
    return L;
};

export const LunarMonth11 = (Y = 0) => {
    const off = LocalToJD(31, 12, Y) - 2415021.076998695;
    const k = INT(off / 29.530588853);
    let jd = NewMoon(k);
    const ret = LocalFromJD(jd);
    const sunLong = SunLongitude(LocalToJD(ret.dd, ret.mm, ret.yyyy)); // sun longitude at local midnight
    if (sunLong > (3 * PI) / 2) {
        jd = NewMoon(k - 1);
    }
    return LocalFromJD(jd);
};

export const initLeapYear = (ret: any) => {
    const sunLongitudes = [ret.length];
    for (let index = 0; index < ret.length; index++) {
        const a = ret[index];
        const jdAtMonthBegin = LocalToJD(a[0], a[1], a[2]);
        sunLongitudes[index] = SunLongitude(jdAtMonthBegin);
    }
    let found = false;
    for (let index = 0; index < ret.length; index++) {
        if (found) {
            ret[index][3] = MOD(index + 10, 12);
            continue;
        }
        const sl1 = sunLongitudes[index];
        const sl2 = sunLongitudes[index + 1];
        const hasMajorTerm =
            Math.floor((sl1 / PI) * 6) !== Math.floor((sl2 / PI) * 6);
        if (!hasMajorTerm) {
            found = true;
            ret[index][4] = 1;
            ret[index][3] = MOD(index + 10, 12);
        }
    }
};

export const LunarYear = (Y = 0) => {
    let ret: any = chunk(range(13 * 5), 5);
    const month11A = LunarMonth11(Y - 1);
    const jdMonth11A = LocalToJD(month11A.dd, month11A.mm, month11A.yyyy);
    const k = Math.floor(0.5 + (jdMonth11A - 2415021.076998695) / 29.530588853);
    const month11B = LunarMonth11(Y);
    const off = LocalToJD(month11B.dd, month11B.mm, month11B.yyyy) - jdMonth11A;

    const leap = off > 365.0;

    if (!leap) {
        ret = chunk(range(13 * 5), 5);
    }

    ret[0] = [month11A.dd, month11A.mm, month11A.yyyy, 0, 0];
    ret[ret.length - 1] = [month11B.dd, month11B.mm, month11B.yyyy, 0, 0];
    for (let index = 1; index < ret.length - 1; index++) {
        const nm = NewMoon(k + index);
        const a = LocalFromJD(nm);
        ret[index] = [a.dd, a.mm, a.yyyy, 0, 0];
    }
    for (let index = 0; index < ret.length; index++) {
        ret[index][3] = MOD(index + 11, 12);
    }
    if (leap) {
        initLeapYear(ret);
    }
    return ret;
};

// dương sang âm
export const onSolar2Lunar = (D = 0, M = 0, Y = 0) => {
    let yy = Y;
    let ly = LunarYear(Y);

    const month11 = ly[ly.length - 1];
    const jdToday = LocalToJD(D, M, Y);
    const jdMonth11 = LocalToJD(month11[0], month11[1], month11[2]);
    if (jdToday >= jdMonth11) {
        ly = LunarYear(Y + 1);
        yy = Y + 1;
    }
    let index = Number(ly.length - 1);
    while (jdToday < LocalToJD(ly[index][0], ly[index][1], ly[index][2])) {
        index--;
    }
    const dd =
        jdToday - LocalToJD(ly[index][0], ly[index][1], ly[index][2]) + 1;
    const mm = ly[index][3];
    if (mm >= 11) {
        yy--;
    }
    const ix = ly[index][4];
    return {
        dd,
        mm,
        yy,
        ix,
        LLLL: `${dd}/${mm}/${yy}`,
        DM: `${dd}/${mm}`,
    };
};

// âm sang dương
export const Lunar2Solar = (D = 0, M = 0, Y = 0, leap = 0) => {
    let yy = Y;
    if (M >= 11) {
        yy = Y + 1;
    }
    const lunarYear = LunarYear(yy);
    let lunarMonth = null;

    for (const index of lunarYear) {
        const lm = lunarYear[index];
        if (lm[3] === M && lm[4] === leap) {
            lunarMonth = lm;
            break;
        }
    }
    if (lunarMonth != null) {
        const jd = LocalToJD(lunarMonth[0], lunarMonth[1], lunarMonth[2]);
        return LocalFromJD(jd + D - 1);
    } else {
        return null;
    }
};

It’s very simple, right? It’s all there.

The next part is Countdown

Source : https://viblo.asia/p/calendar-voi-reactjs-typescript-su-dung-moment-5OXLAAwkLGr

Please follow and like us:
Pin Share

This Post Has 574 Comments

  1. mostbet_pbMi

    mostbet qeydiyyat bonus [url=mostbet3041.ru]mostbet3041.ru[/url]

  2. 1win_bnKr

    1win играть [url=http://1win1138.ru/]http://1win1138.ru/[/url]

  3. Robertroola

    jouer au cinema Seminaires de theatre Conservatoire d’art dramatique Academie de cinema Seances d’art dramatique Lycee d’art dramatique Centre de production cinematographique S’epanouir en tant qu’acteur Formation d’acteur professionnelle Cours de jeu d’acteur a Paris Se produire dans des films

  4. DavidRes

    работа военным Служба в армии – это школа жизни, которая закаляет характер, учит преодолевать трудности и ценить простые вещи.

  5. kashpo napolnoe_wjPi

    купить высокие горшки для цветов пластиковые напольные [url=https://kashpo-napolnoe-rnd.ru]купить высокие горшки для цветов пластиковые напольные[/url] .

  6. DavidRes

    работа военным Работа военным: защита Отечества Работа военным – это защита Отечества. Это священный долг каждого гражданина, готового встать на защиту своей Родины в трудную минуту. Военная служба – это не просто работа, это призвание, требующее мужества, отваги и самоотверженности. Военные – это люди, которые прошли специальную подготовку, владеют современным оружием и техникой, готовы выполнить любой приказ, защитить свою страну от внешних угроз. Они стоят на страже мира и спокойствия, обеспечивая безопасность граждан. Военная служба – это возможность получить уникальный опыт, развить свои физические и моральные качества, научиться преодолевать трудности и нести ответственность за свои действия. Военные – это сильные и уверенные в себе люди, способные принимать решения в сложных ситуациях. Армия – это школа жизни, которая воспитывает патриотизм, дисциплину и уважение к старшим. Военные – это пример для подражания, люди, которые своим примером вдохновляют молодежь на служение Родине. Государство заботится о своих защитниках, предоставляя им достойное денежное довольствие, жилье, медицинское обслуживание и другие социальные гарантии. Военная служба – это стабильность и уверенность в завтрашнем дне. Работа военным – это возможность внести свой вклад в развитие страны, в укрепление ее обороноспособности и международного авторитета. Военные участвуют в научных исследованиях, разрабатывают новые виды вооружения и техники, повышают боеготовность армии. Военная служба – это нелегкий труд, требующий постоянного совершенствования, физической и моральной подготовки. Но это также возможность почувствовать себя частью сильной и сплоченной команды, гордиться своей профессией и служением Родине. Работа военным – это выбор настоящих героев, готовых отдать свою жизнь за свободу и независимость своей страны.

  7. kashpo napolnoe_fnPi

    купить напольные горшки недорого [url=http://www.kashpo-napolnoe-rnd.ru]купить напольные горшки недорого[/url] .

  8. Charlesbremi

    Отзывы о целителях Очищение от негатива – процесс избавления от отрицательных эмоций и энергий, мешающих гармоничной жизни.

  9. 1win_qlEa

    1win voucher code [url=1win3024.com]1win voucher code[/url]

  10. 1win_qskt

    1win bonus casino how to use [url=https://1win3026.com]1win bonus casino how to use[/url]

  11. Stevenjag

    макрос варфейс x7 Устали от отдачи в Warface? Не ищите варфейс макрос бесплатно, а выбирайте проверенные решения! Это гарантия точности и контроля над оружием. Начните побеждать уже сегодня!

  12. 1win_ujmn

    1win games [url=http://1win3025.com]1win games[/url]

  13. ThomasSycle

    рулонные шторы пятигорск купить Шторы Оптом Пятигорск: Выгодное Предложение для Бизнеса Для оптовых покупателей в Пятигорске предлагаются выгодные условия на приобретение штор. Многие компании сотрудничают с оптовыми клиентами, предлагая широкий ассортимент продукции и гибкую систему скидок.

  14. Stephender

    Hi there! I understand this is kind of off-topic however I had to ask. Does running a well-established website such as yours require a large amount of work? I’m brand new to blogging however I do write in my journal every day. I’d like to start a blog so I can easily share my personal experience and thoughts online. Please let me know if you have any kind of ideas or tips for brand new aspiring blog owners. Appreciate it!
    24/7 limo near me

  15. mostbet_onpa

    mostbet az virtual oyunlar [url=www.mostbet4052.ru]mostbet az virtual oyunlar[/url]

  16. 1win_azml

    1win bonus casino how to use [url=https://1win3028.com/]https://1win3028.com/[/url]

Leave a Reply