Skip to content

Instantly share code, notes, and snippets.

@g4rcez
Created January 14, 2025 00:26
Show Gist options
  • Save g4rcez/c506cd1b89e90cb26c15033db5302d71 to your computer and use it in GitHub Desktop.
Save g4rcez/c506cd1b89e90cb26c15033db5302d71 to your computer and use it in GitHub Desktop.
import {
add,
set,
format,
startOfWeek,
endOfWeek,
eachDayOfInterval,
isBefore,
} from "npm:date-fns";
/*
* Explicação da regex
(?<startDate>
(
define: próximo dia da semana
(?<nextWeekDay>(pr[oó]xim[ao])? (((segunda|terça|quarta|quinta|sexta)(-| )feira)|s[aá]bado|domingo))
define: amanhã
|(?<tomorrow>amanh[aã])
)
define: às HH:mm
(às ([0-9][0-9]:[0-9][0-9]|[0-9][0-9]h)?)
)
*/
type RegexMatch = Partial<{
startDate: string;
nextWeekDay: string;
tomorrow: string;
startTime: string;
}>;
const matchTime = /(\d\d:\d\d|\d\dh)/i;
type DateOnlyOperator = {
regex: RegExp;
fn: (d: Date) => Date;
};
const dateOnlyOperator: DateOnlyOperator[] = [
{
regex: /domingo/,
fn: (d: Date): Date => {
const range = eachDayOfInterval({
start: startOfWeek(d),
end: endOfWeek(d),
});
const weekDay = +format(d, "i"); // 1 até 7 -> 0 até 6
const result = range[weekDay - 1];
if (isBefore(result, d)) {
const nextWeek = add(d, { weeks: 1 });
const range = eachDayOfInterval({
start: startOfWeek(nextWeek),
end: endOfWeek(nextWeek),
});
return range[weekDay - 1];
}
return result;
},
},
{
regex: /amanh[ãa]/,
fn: (d: Date): Date => add(d, { days: 1 }),
},
];
const parseStartDateOnly = (match: RegexMatch): Date => {
const now = new Date();
if (!match.startDate) return now;
const find = dateOnlyOperator.find((x) =>
x.regex.exec(match.startDate || "")
);
if (!find) return now;
return find.fn(now);
};
const sanitizeTime = (t: string) => t.replace(/h$/g, "");
const setTime = (d: Date, timeString: string) => {
const [hours, minutes = "0"] = sanitizeTime(timeString).split(":");
console.log({ hours, minutes });
if (hours && minutes) {
return set(d, { hours: Number(hours), minutes: Number(minutes) });
}
return d;
};
export const parseStartDate = (match: RegexMatch) => {
const time = matchTime.exec(match.startTime || "")?.[0];
const date = parseStartDateOnly(match);
if (time) return setTime(date, time);
return date;
};
const regex =
/(?<startDate>((?<nextWeekDay>(pr[oó]xim[ao])? (((segunda|terça|quarta|quinta|sexta)(-| )feira)|s[aá]bado|domingo))|(?<tomorrow>amanh[aã])) (?<startTime>às ([0-9][0-9]:[0-9][0-9]|[0-9][0-9]h)?))/i;
const sentence = "Dever de casa número 5 para domingo às 16h";
const match = regex.exec(sentence);
const result = parseStartDate(match?.groups || {});
console.log("pt-BR:", result.toLocaleString("pt-BR"));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment