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

- 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);
- 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;
- 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);
};
- 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;
};
- 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
mostbet qeydiyyat bonus [url=mostbet3041.ru]mostbet3041.ru[/url]
1win играть [url=http://1win1138.ru/]http://1win1138.ru/[/url]
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
работа военным Служба в армии – это школа жизни, которая закаляет характер, учит преодолевать трудности и ценить простые вещи.
https://stroidom36.ru/bystrovozvodimye-doma/ Натяжные потолки в Воронеже: установка и выбор дизайна
купить высокие горшки для цветов пластиковые напольные [url=https://kashpo-napolnoe-rnd.ru]купить высокие горшки для цветов пластиковые напольные[/url] .
работа военным Работа военным: защита Отечества Работа военным – это защита Отечества. Это священный долг каждого гражданина, готового встать на защиту своей Родины в трудную минуту. Военная служба – это не просто работа, это призвание, требующее мужества, отваги и самоотверженности. Военные – это люди, которые прошли специальную подготовку, владеют современным оружием и техникой, готовы выполнить любой приказ, защитить свою страну от внешних угроз. Они стоят на страже мира и спокойствия, обеспечивая безопасность граждан. Военная служба – это возможность получить уникальный опыт, развить свои физические и моральные качества, научиться преодолевать трудности и нести ответственность за свои действия. Военные – это сильные и уверенные в себе люди, способные принимать решения в сложных ситуациях. Армия – это школа жизни, которая воспитывает патриотизм, дисциплину и уважение к старшим. Военные – это пример для подражания, люди, которые своим примером вдохновляют молодежь на служение Родине. Государство заботится о своих защитниках, предоставляя им достойное денежное довольствие, жилье, медицинское обслуживание и другие социальные гарантии. Военная служба – это стабильность и уверенность в завтрашнем дне. Работа военным – это возможность внести свой вклад в развитие страны, в укрепление ее обороноспособности и международного авторитета. Военные участвуют в научных исследованиях, разрабатывают новые виды вооружения и техники, повышают боеготовность армии. Военная служба – это нелегкий труд, требующий постоянного совершенствования, физической и моральной подготовки. Но это также возможность почувствовать себя частью сильной и сплоченной команды, гордиться своей профессией и служением Родине. Работа военным – это выбор настоящих героев, готовых отдать свою жизнь за свободу и независимость своей страны.
купить напольные горшки недорого [url=http://www.kashpo-napolnoe-rnd.ru]купить напольные горшки недорого[/url] .
записаться к психологу Консультация психолога: Первый шаг к решению проблем. Профессиональная помощь в поиске выхода из сложных ситуаций.
Грузоперевозки Луганск Упаковка грузов Луганск: Профессиональная упаковка грузов для обеспечения их сохранности при транспортировке.
Отзывы о целителях Очищение от негатива – процесс избавления от отрицательных эмоций и энергий, мешающих гармоничной жизни.
Эфирные масла и медитация: как достичь гармонии Эфирные масла doTERRA для здоровья. Натуральные помощники в укреплении иммунитета, облегчении дыхания, снятии мышечного напряжения. Лаванда для спокойствия, лимон для энергии, чайное дерево для защиты.
1win voucher code [url=1win3024.com]1win voucher code[/url]
Грузоперевозки Луганск Перевозка сейфов Луганск: Перевозка сейфов и других тяжеловесных предметов.
1win bonus casino how to use [url=https://1win3026.com]1win bonus casino how to use[/url]
завьялов илья поинт пей PointPay: Илья Завьялов о важности открытого диалога и сотрудничества с регуляторами
Профессиональная наркологическая клиника казань. Лечение зависимостей, капельницы, вывод из запоя, реабилитация. Анонимно, круглосуточно, с поддержкой врачей и психологов.
макрос варфейс x7 Устали от отдачи в Warface? Не ищите варфейс макрос бесплатно, а выбирайте проверенные решения! Это гарантия точности и контроля над оружием. Начните побеждать уже сегодня!
1win games [url=http://1win3025.com]1win games[/url]
рулонные шторы пятигорск купить Шторы Оптом Пятигорск: Выгодное Предложение для Бизнеса Для оптовых покупателей в Пятигорске предлагаются выгодные условия на приобретение штор. Многие компании сотрудничают с оптовыми клиентами, предлагая широкий ассортимент продукции и гибкую систему скидок.
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
завьялов илья поинт пей Завьялов Илья: PointPay как пример социальной ответственности в крипто-бизнесе
mostbet az virtual oyunlar [url=www.mostbet4052.ru]mostbet az virtual oyunlar[/url]
1win bonus casino how to use [url=https://1win3028.com/]https://1win3028.com/[/url]