core: fix timezone
Signed-off-by: Rodrigo Bertoldo de Sousa Martins <rodrigo.sousa.577@gmail.com>
This commit is contained in:
1 parent
5193b2df08
commit
c42202b727
3 files changed
+81
-22
No files matched your search
@@ -33,6 +33,7 @@ EXPOSE 3000
|
|||||||
# Definir variáveis de ambiente padrão
|
# Definir variáveis de ambiente padrão
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
ENV BOT_DEBUG=false
|
ENV BOT_DEBUG=false
|
||||||
|
ENV TZ=America/Araguaina
|
||||||
|
|
||||||
# Health check
|
# Health check
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ services:
|
|||||||
# Usuários autorizados
|
# Usuários autorizados
|
||||||
- ALLOWED_USERS=${ALLOWED_USERS}
|
- ALLOWED_USERS=${ALLOWED_USERS}
|
||||||
|
|
||||||
|
# Fuso horário
|
||||||
|
- TZ=America/Araguaina
|
||||||
|
|
||||||
# Volumes para logs persistentes
|
# Volumes para logs persistentes
|
||||||
volumes:
|
volumes:
|
||||||
- ./logs:/app/logs
|
- ./logs:/app/logs
|
||||||
|
|||||||
+77
-22
@@ -111,10 +111,13 @@ class DateProcessor {
|
|||||||
|
|
||||||
if (this.diasSemana.hasOwnProperty(diaNome)) {
|
if (this.diasSemana.hasOwnProperty(diaNome)) {
|
||||||
const diaSemanaTarget = this.diasSemana[diaNome];
|
const diaSemanaTarget = this.diasSemana[diaNome];
|
||||||
const data = this.obterProximoDiaSemana(diaSemanaTarget);
|
const proxData = this.obterProximoDiaSemana(diaSemanaTarget);
|
||||||
data.setHours(hora, minuto, 0, 0);
|
|
||||||
|
|
||||||
if (this.isValidTime(hora, minuto)) {
|
if (this.isValidTime(hora, minuto)) {
|
||||||
|
// Obter componentes da data no fuso Brasil
|
||||||
|
const partes = this.extrairPartesBrasil(proxData);
|
||||||
|
const data = this.criarDataBrasil(partes.ano, partes.mes, partes.dia, hora, minuto);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
data,
|
data,
|
||||||
@@ -153,11 +156,15 @@ class DateProcessor {
|
|||||||
|
|
||||||
if (this.palavrasTemporais.hasOwnProperty(palavraTemporal)) {
|
if (this.palavrasTemporais.hasOwnProperty(palavraTemporal)) {
|
||||||
const diasOffset = this.palavrasTemporais[palavraTemporal];
|
const diasOffset = this.palavrasTemporais[palavraTemporal];
|
||||||
const data = new Date();
|
|
||||||
data.setDate(data.getDate() + diasOffset);
|
|
||||||
data.setHours(hora, minuto, 0, 0);
|
|
||||||
|
|
||||||
if (this.isValidTime(hora, minuto)) {
|
if (this.isValidTime(hora, minuto)) {
|
||||||
|
// Basear no dia atual no fuso Brasil e aplicar offset
|
||||||
|
const hoje = this.extrairPartesBrasil(new Date());
|
||||||
|
const base = this.criarDataBrasil(hoje.ano, hoje.mes, hoje.dia, 12, 0);
|
||||||
|
base.setDate(base.getDate() + diasOffset);
|
||||||
|
const partes = this.extrairPartesBrasil(base);
|
||||||
|
const data = this.criarDataBrasil(partes.ano, partes.mes, partes.dia, hora, minuto);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
data,
|
data,
|
||||||
@@ -213,7 +220,7 @@ class DateProcessor {
|
|||||||
if (ano < 100) ano += 2000; // Converter anos de 2 dígitos
|
if (ano < 100) ano += 2000; // Converter anos de 2 dígitos
|
||||||
|
|
||||||
if (mes !== undefined && this.isValidDate(dia, mes, ano) && this.isValidTime(hora, minuto)) {
|
if (mes !== undefined && this.isValidDate(dia, mes, ano) && this.isValidTime(hora, minuto)) {
|
||||||
const data = new Date(ano, mes, dia, hora, minuto, 0, 0);
|
const data = this.criarDataBrasil(ano, mes, dia, hora, minuto);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
@@ -251,34 +258,55 @@ class DateProcessor {
|
|||||||
const quantidade = parseInt(match[1]);
|
const quantidade = parseInt(match[1]);
|
||||||
const unidade = match[2].toLowerCase();
|
const unidade = match[2].toLowerCase();
|
||||||
|
|
||||||
const data = new Date();
|
let data = new Date();
|
||||||
|
|
||||||
if (unidade.includes('dia')) {
|
if (unidade.includes('dia')) {
|
||||||
data.setDate(data.getDate() + quantidade);
|
const base = this.extrairPartesBrasil(new Date());
|
||||||
|
const tmpDate = this.criarDataBrasil(base.ano, base.mes, base.dia, 12, 0);
|
||||||
|
tmpDate.setDate(tmpDate.getDate() + quantidade);
|
||||||
if (match[3] && match[4] !== undefined) {
|
if (match[3] && match[4] !== undefined) {
|
||||||
const hora = parseInt(match[3]);
|
const hora = parseInt(match[3]);
|
||||||
const minuto = match[4] ? parseInt(match[4]) : 0;
|
const minuto = match[4] ? parseInt(match[4]) : 0;
|
||||||
if (this.isValidTime(hora, minuto)) {
|
if (this.isValidTime(hora, minuto)) {
|
||||||
data.setHours(hora, minuto, 0, 0);
|
const partes = this.extrairPartesBrasil(tmpDate);
|
||||||
|
data = this.criarDataBrasil(partes.ano, partes.mes, partes.dia, hora, minuto);
|
||||||
|
} else {
|
||||||
|
data = tmpDate;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
data = tmpDate;
|
||||||
}
|
}
|
||||||
} else if (unidade.includes('semana')) {
|
} else if (unidade.includes('semana')) {
|
||||||
data.setDate(data.getDate() + (quantidade * 7));
|
const base = this.extrairPartesBrasil(new Date());
|
||||||
|
const tmpDate = this.criarDataBrasil(base.ano, base.mes, base.dia, 12, 0);
|
||||||
|
tmpDate.setDate(tmpDate.getDate() + (quantidade * 7));
|
||||||
if (match[3] && match[4] !== undefined) {
|
if (match[3] && match[4] !== undefined) {
|
||||||
const hora = parseInt(match[3]);
|
const hora = parseInt(match[3]);
|
||||||
const minuto = match[4] ? parseInt(match[4]) : 0;
|
const minuto = match[4] ? parseInt(match[4]) : 0;
|
||||||
if (this.isValidTime(hora, minuto)) {
|
if (this.isValidTime(hora, minuto)) {
|
||||||
data.setHours(hora, minuto, 0, 0);
|
const partes = this.extrairPartesBrasil(tmpDate);
|
||||||
|
data = this.criarDataBrasil(partes.ano, partes.mes, partes.dia, hora, minuto);
|
||||||
|
} else {
|
||||||
|
data = tmpDate;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
data = tmpDate;
|
||||||
}
|
}
|
||||||
} else if (unidade.includes('mes')) {
|
} else if (unidade.includes('mes')) {
|
||||||
data.setMonth(data.getMonth() + quantidade);
|
const base = this.extrairPartesBrasil(new Date());
|
||||||
|
const tmpDate = this.criarDataBrasil(base.ano, base.mes, base.dia, 12, 0);
|
||||||
|
tmpDate.setMonth(tmpDate.getMonth() + quantidade);
|
||||||
if (match[3] && match[4] !== undefined) {
|
if (match[3] && match[4] !== undefined) {
|
||||||
const hora = parseInt(match[3]);
|
const hora = parseInt(match[3]);
|
||||||
const minuto = match[4] ? parseInt(match[4]) : 0;
|
const minuto = match[4] ? parseInt(match[4]) : 0;
|
||||||
if (this.isValidTime(hora, minuto)) {
|
if (this.isValidTime(hora, minuto)) {
|
||||||
data.setHours(hora, minuto, 0, 0);
|
const partes = this.extrairPartesBrasil(tmpDate);
|
||||||
|
data = this.criarDataBrasil(partes.ano, partes.mes, partes.dia, hora, minuto);
|
||||||
|
} else {
|
||||||
|
data = tmpDate;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
data = tmpDate;
|
||||||
}
|
}
|
||||||
} else if (unidade.includes('hora')) {
|
} else if (unidade.includes('hora')) {
|
||||||
data.setHours(data.getHours() + quantidade);
|
data.setHours(data.getHours() + quantidade);
|
||||||
@@ -340,6 +368,31 @@ class DateProcessor {
|
|||||||
return hora >= 0 && hora <= 23 && minuto >= 0 && minuto <= 59;
|
return hora >= 0 && hora <= 23 && minuto >= 0 && minuto <= 59;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Criar um Date com hora no fuso America/Araguaina,
|
||||||
|
* independente do TZ do servidor.
|
||||||
|
*/
|
||||||
|
criarDataBrasil(ano, mes, dia, hora, minuto) {
|
||||||
|
// Constrói uma string ISO no fuso -03:00 para garantir
|
||||||
|
// que a hora digitada pelo usuário seja tratada como BR.
|
||||||
|
const pad = (n) => String(n).padStart(2, '0');
|
||||||
|
const isoStr = `${ano}-${pad(mes + 1)}-${pad(dia)}T${pad(hora)}:${pad(minuto)}:00-03:00`;
|
||||||
|
return new Date(isoStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extrair {ano, mes(0-11), dia} de um Date no fuso Brasil.
|
||||||
|
*/
|
||||||
|
extrairPartesBrasil(data) {
|
||||||
|
const fmt = new Intl.DateTimeFormat('en-CA', {
|
||||||
|
timeZone: 'America/Araguaina',
|
||||||
|
year: 'numeric', month: '2-digit', day: '2-digit'
|
||||||
|
});
|
||||||
|
// en-CA produz YYYY-MM-DD
|
||||||
|
const [ano, mes, dia] = fmt.format(data).split('-').map(Number);
|
||||||
|
return { ano, mes: mes - 1, dia };
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formatar data para string legível
|
* Formatar data para string legível
|
||||||
*/
|
*/
|
||||||
@@ -352,7 +405,7 @@ class DateProcessor {
|
|||||||
day: 'numeric',
|
day: 'numeric',
|
||||||
hour: '2-digit',
|
hour: '2-digit',
|
||||||
minute: '2-digit',
|
minute: '2-digit',
|
||||||
timeZone: 'America/Sao_Paulo'
|
timeZone: 'America/Araguaina'
|
||||||
};
|
};
|
||||||
|
|
||||||
return data.toLocaleDateString('pt-BR', opcoes);
|
return data.toLocaleDateString('pt-BR', opcoes);
|
||||||
@@ -360,18 +413,20 @@ class DateProcessor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Formatar data para o formato do sistema (YYYY-MM-DD HH:mm:ss)
|
* Formatar data para o formato do sistema (YYYY-MM-DD HH:mm:ss)
|
||||||
|
* Retorna sempre no horário de Brasília.
|
||||||
*/
|
*/
|
||||||
formatarParaSistema(data) {
|
formatarParaSistema(data) {
|
||||||
if (!(data instanceof Date)) return null;
|
if (!(data instanceof Date)) return null;
|
||||||
|
|
||||||
const ano = data.getFullYear();
|
// Formata no fuso de Brasília para não depender do TZ do servidor
|
||||||
const mes = String(data.getMonth() + 1).padStart(2, '0');
|
const fmt = new Intl.DateTimeFormat('sv-SE', {
|
||||||
const dia = String(data.getDate()).padStart(2, '0');
|
timeZone: 'America/Araguaina',
|
||||||
const hora = String(data.getHours()).padStart(2, '0');
|
year: 'numeric', month: '2-digit', day: '2-digit',
|
||||||
const minuto = String(data.getMinutes()).padStart(2, '0');
|
hour: '2-digit', minute: '2-digit', second: '2-digit',
|
||||||
const segundo = String(data.getSeconds()).padStart(2, '0');
|
hour12: false
|
||||||
|
});
|
||||||
return `${ano}-${mes}-${dia} ${hora}:${minuto}:${segundo}`;
|
// sv-SE produz YYYY-MM-DD HH:mm:ss
|
||||||
|
return fmt.format(data).replace('T', ' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user