Каскадное манипулирование датой и старшинство [duplicate]

Если вы можете передавать файлы в систему и из нее, сделайте резервную копию текущего crontab:

$ crontab -l >crontab.txt

Если вы не можете выполнять перенаправления, просто выполните crontab -lи скопируйте и вставьте crontab (убедившись, что все идентично).

Затем, с текстовым файлом crontab в не очень заблокированной системе, обновите его в редакторе.

Перенесите файл обратно и выполните

$ crontab crontab.txt

Это должно быть правильно протестировано на идентичном сервере разработки, включая правильность спецификаций задания, перед внедрением на рабочем сервере. Обратите внимание, что загрузка crontab в crontabтаким образом заменяет текущий crontab.

Я не беру на себя никакой ответственности.

0
09.02.2018, 00:29
3 ответа

No, no hay orden de precedencia.

Irónicamente, esto acaba de aparecer en la lista de correo de los usuarios de Debian este mes, donde se señaló que para un ser humano que lee el supuesto lenguaje natural legible -humano, la manipulación de fechas ordena el comportamiento de GNU dateherramienta parece bastante enloquecedoramente inconsistente. Vincent Lefèvre dio estos ejemplos:

jdebp % date +%Y-%m-%d -d '2003-02-01 - 1 month'
2003-01-01
jdebp % date +%Y-%m-%d -d '2003-02-01 - 31 days'
2003-01-01
jdebp % date +%Y-%m-%d -d '2003-02-01 - 31 days + 1 month'
2003-01-29
jdebp % date +%Y-%m-%d -d '2003-02-01 - 1 month + 1 month'
2003-02-01
jdebp % date +%Y-%m-%d -d '2003-09-01 1 day ago + 1 month'
2003-09-30
jdebp % date +%Y-%m-%d -d '2003-09-01 1 day ago'
2003-08-31
jdebp % date +%Y-%m-%d -d '2003-08-31 + 1 month'
2003-10-01
jdebp %

Lo que realmente sucede internamente en datees que durante el cálculo se construyen fechas intermedias no válidas con valores negativos en lugares, como 2003-03-(-30)por ejemplo. Luego vuelve a normalizar estas fechas no válidas después de que todo esté hecho, utilizando una función de la biblioteca estándar del lenguaje C.

Lo que no está haciendo es renormalizar en cada paso , como lo hace un humano. Así que 2003 -02 -01 menos 31 días para el programa GNU datees una fecha no válida, el 30 de febrero negativo , y no una fecha válida en enero como podría calcular un ser humano. Agregue un mes, y eso se convierte en una fecha no válida en marzo, aún el 30 negativo,que finalmente se vuelve a normalizar a esa fecha en enero porque, por supuesto, al ajustarse para convertir -30en un número mayor que cero, se salta todo el mes de febrero. Las fechas no válidas sin volver a normalizar en los otros ejemplos son 2003-10-00, 2003-09-00y 2003-09-31.

Aplicando esto a su ejemplo:

  • 2017-12-31 + 1 dayes 2017-12-32, que se vuelve a normalizar a 2018-01-01en la salida del programa.
  • 2018-01-01 - 1 monthes 2018-00-01, que se vuelve a normalizar a 2017-12-01en la salida del programa.
  • 2017-12-31 + 1 day - 1 monthes 2017-11-32, que se vuelve a normalizar a 2017-12-02en la salida del programa.

Como puede ver cuando vuelve a normalizar en cada paso no obtiene el mismo resultado que aplicando todos los cambios de una sola vez, porque GNU dateaplica múltiples cambios de una vez no vuelve a normalizar en cada paso .

Lecturas adicionales

2
28.01.2020, 02:32

La razón es que esto sucede:

$ a=20171231; b=$(date -d "$a  -1 month"); echo "<$b>"
<Fri Dec  1 00:00:00 PST 2017>

La fecha de mando va al principio del mes de diciembre.
Cuando agrega 1 día, pasa al día 2.

En cambio, cuando el día es 1 de enero se retrocede un mes completo

$ a=20180101; b=$(date -d "$a -1 month"); echo "<$b>"
<Fri Dec  1 00:00:00 PST 2017>

Esa es una característica interna de la fecha.

datevuelve al mes anterior con el mismo número de día dado:

$ a=20171110; b=$(date -d "$a -1 month"); echo "<$b>"
<Tue Oct 10 00:00:00 PST 2017>

Esa es la fecha dada en noviembre se remonta a octubre. Pero si el día es 31 se mete en problemas. Por ejemplo del 31 de octubre no hay 31 de septiembre, por lo que se remonta al 1 de octubre:

$ a=20171031; b=$(date -d "$a -1 month"); echo "<$b>"
<Sun Oct  1 00:00:00 AST 2017>

Los cambios de mes son exactos solo cuando el día es 01, febrero es un mes particularmente extraño:

$ a=20170331; b=$(date -d "$a -1 month"); echo "<$b>"
<Fri Mar  3 00:00:00 AST 2017>

Porque no hay 31 de febrero.

0
28.01.2020, 02:32

Me parece que dateprimero retrocede un mes, y luego agrega el día, en este orden.

Si cambias el orden de las operaciones en el pipeline, obtienes el mismo resultado que con la otra.

$ echo 20171231 | xargs -i date -d "{} -1 month" | xargs -i date -d "{} +1 day"
Sat Dec  2 00:00:00 EET 2017

Lo que pasa es que retroceder un mes del 31 de diciembre es problemático. La misma fecha en el mes anterior sería el 31 de noviembre, pero noviembre solo tiene 30 días. En cierto sentido, el 31 de noviembre es lo mismo que el 1 de diciembre, por lo que dar este último tiene algo de lógica.

Por supuesto, otra opción sería ir del 31 de diciembre al 30 de noviembre, pero eso tampoco está completamente libre de problemas. ¿Debe Nov 30 - 1 monthser el 30 de octubre o el 31 de octubre?

Es posible que deba implementar la lógica requerida manualmente.

0
28.01.2020, 02:32

Теги

Похожие вопросы