/** * `DateUtils`: Utilizado para formatação, padronização e cálculos de datas. */ export default class DateUtils{ /** * Zerar o horário de uma data. * * @param date - Data a ser manipulada. * @param adjustDayLightSavingTime - Ajusta horário de verão na data recebida. * @returns - Data sem as informações de horário. * @example * Informo: 2023-03-09 12:42:40 | Obtenho: 2023-03-09 00:00:00 */ public static clearTime(date:Date, adjustDayLightSavingTime:boolean = true): Date { const newDate: Date = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0); return adjustDayLightSavingTime ? DateUtils.adjustDLST(newDate) : newDate; } /** * Converte data para uma string no formato pt-BR. * * @param date - Data a ser convertida. * @param options - Opções de formatação da data. * @returns - Uma string com a data no formato pt-BR DD/MM/YYYY. */ public static formatDate(date: Date, options?: Intl.DateTimeFormatOptions): string{ if(typeof date === "string"){ return date; } return date ? new Intl.DateTimeFormat("pt-BR", options ?? {}).format(date) : ""; } /** * Converte as horas de uma data para uma string pt-BR. * * @param date - Data a ser convertida. * @param showSeconds - define se devemos considerar os segundos. * @returns - Uma string com as horas no formato HH:MM ou HH:MM:SS. */ public static formatTime(date: Date, showSeconds: boolean = false): string{ if (date == null){ return ''; } const timeOptions:Intl.DateTimeFormatOptions = {hour: "2-digit", minute: "2-digit", second: showSeconds ? "2-digit" : undefined}; return new Intl.DateTimeFormat("pt-BR", timeOptions).format(date); } /** * Converte a data e hora para uma string no formato pt-BR. * * @param date - Data a ser convertida. * @param showSeconds - define se devemos considerar os segundos. * @returns - Uma string com as horas no formato DD/MM/YYYY HH:MM ou DD/MM/YYYY HH:MM:SS. */ public static formatDateTime(date: Date, showSeconds: boolean = false): string{ return `${DateUtils.formatDate(date)} ${DateUtils.formatTime(date, showSeconds)}`; } /** * Converte String para Date. * * @param strValue - Texto a ser convertido para data. * @param adjustDayLightSavingTime - Se verdadeiro, ativa regra de horário de verão. * @param monthYearMode - Quando ativado, retorna o primeiro dia do mês apenas para construir a data. * @returns - Data sem as informações de horário. */ public static strToDate(strValue:string, adjustDayLightSavingTime:boolean = true, monthYearMode:boolean = false): Date | undefined { /** monthYearMode é um booleano para usar o formato MM/YYYY. * Quando ativado, é retornado o primeiro dia do mês apenas para construir a data. * Não há necessidade de verificar o horário de verão quando utilizado esse modo. */ let parts; if (monthYearMode) { parts = /^(1[0-2]|0[1-9]|[1-9])[^\d]?(\d{2}|\d{4})(?:\s(\d{1,2}):(\d{1,2}):?(\d{0,2}))?$/.exec(strValue); }else { parts = /^(3[01]|[1-2]\d|0[1-9]|[1-9])[^\d]?(1[0-2]|0[1-9]|[1-9])[^\d]?(\d{2}|\d{4})(?:\s(\d{1,2}):(\d{1,2}):?(\d{0,2}))?$/.exec(strValue); } if (!parts) { return undefined; } const day:number = monthYearMode ? 1 : Number(parts[1]); const month:number = Number(parts[(monthYearMode ? 1 : 2)]); let year:number = Number(parts[(monthYearMode ? 2 : 3)]); const hour:number = Number(parts[(monthYearMode ? 3 : 4 )] || 0); const min:number = Number(parts[(monthYearMode ? 4 : 5 )] || 0); const sec:number = Number(parts[(monthYearMode ? 5 : 6 )] || 0); if (year < 100) { year += year < 30 ? 2000 : 1900; } let date: Date = new Date(year, month - 1, day, hour, min, sec, 0); if (adjustDayLightSavingTime === true && !monthYearMode && hour == 0) { date = DateUtils.adjustDLST(date); } return date; } /** * Obtém a data atual. * * @param withTime - Caso true retorna a data com informações de horário. * @returns - Data atual sem informação de horário. */ public static getToday(withTime: boolean = false): Date { const today = new Date(); if (withTime) { return today; } else { return DateUtils.clearTime(today); } } /** * Retorna se a data é válida. * * @param value - Data a ser validada. * @param hasTime - Determina se a data retornada deve conter informação de horário ou não. Por padrão não retorna a hora. * @returns - Caso válida, retorna a própria data. */ public static validateDate(value: Date, hasTime: boolean = false): Date | undefined { return value instanceof Date && !isNaN(value.valueOf()) ? hasTime ? value : DateUtils.clearTime(value) : undefined; } /** * Realiza correção do horário de verão. * * @param date - Data a ser ajustada. * @returns - Data informada ajustada para horário de verão. */ private static adjustDLST(date:Date): Date { if(date.getHours() == 23){ return new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1, 1, 0, 0, 0); } return date; } /** * Adiciona uma casa decimal a esquerda de uma unidade. * * @param n - Número a ser ajustado * @returns - O número informado, com uma casa decimal a esquerda. * @example * Informo: 15 | Obtenho: 15 * @example * Informo: 2 | Obtenho: "02" */ private static pad(n: number): string | number { return n < 10 ? "0" + n : n; } /** * Retorna timezone da data. * * @param offset - Valor do timezone desejado. * @returns Timezone da data. */ private static timezoneOffset(offset: number): string { let sign; if (offset === 0) { return "Z"; } sign = (offset > 0) ? "-" : "+"; offset = Math.abs(offset); return sign + this.pad(Math.floor(offset / 60)) + ":" + this.pad(offset % 60); } /** * Converte a data para o formato RFC3339. * * @param date - Data a ser convertida * @returns - Data informada no formato RFC3339. * * @example * Informo: 2023-03-09 12:42:40 | Obtenho: 2023-03-09T12:42:47-03:00 */ public static formatRfc3339(date: Date): string { return date.getFullYear() + "-" + this.pad(date.getMonth() + 1) + "-" + this.pad(date.getDate()) + "T" + this.pad(date.getHours()) + ":" + this.pad(date.getMinutes()) + ":" + this.pad(date.getSeconds()) + this.timezoneOffset(date.getTimezoneOffset()); } }