Иллюстрация из «Путешествия с Go», созданная Рене Френч.
В одном из приложений, над которыми я работаю, я должен рассчитать, что является предыдущим месяцем данной даты. Это кажется легким, не так ли? Голанг предоставляет Временный пакет который имеет метод: добавить.
Я довольно свежий в ходе, ранее я работал с C#, Python и (в течение некоторого времени) Машинопись. У каждого из этих языков также есть некоторые методы для расчета времени. Посмотрим, как они работают.
C# .net 5:
Давайте использовать Система. DateTime. Добавить инты :
using System; public class Program { public static void Main() { var endOfMay = new DateTime(2021, 05, 31, 12, 00, 00); var endOfApril = endOfMay.AddMonths(-1); var enfOfJune = endOfMay.AddMonths(1); Console.WriteLine("End of May: {0}", endOfMay); Console.WriteLine("End of April: {0}", endOfApril); Console.WriteLine("End of June: {0}", enfOfJune); } }
Выход:
End of May: 05/31/2021 12:00:00 End of April: 04/30/2021 12:00:00 End of June: 06/30/2021 12:00:00
Хорошо выглядит 👍
Python 3.9
Здесь я буду использовать DateUtil.RelatativeLeta :
import datetime from dateutil.relativedelta import relativedelta end_of_may = datetime.datetime(2021, 5, 31, 12, 0, 0, 0) end_of_april = end_of_may + relativedelta(months=-1) end_of_june = end_of_may + relativedelta(months=1) print(f'End Of May: {end_of_may}') print(f'End Of April: {end_of_april}') print(f'End of June: {end_of_june}')
Посмотрим журналы:
End Of May: 2021-05-31 12:00:00 End Of April: 2021-04-30 12:00:00 End of June: 2021-06-30 12:00:00
Именно то, что я искал 👌
Идти
Теперь, Код, который сломал мою услугу:
package main import ( "fmt" "time" ) func main() { endOfMay := time.Date(2021, 5, 31, 12, 00, 00, 00, time.UTC) endOfApril := endOfMay.AddDate(0, -1, 0) endOfJune := endOfMay.AddDate(0, 1, 0) fmt.Printf("End of May: %s\n", endOfMay) fmt.Printf("End of April: %s\n", endOfApril) fmt.Printf("End of June: %s\n", endOfJune) }
И вывод:
End of May: 2021-05-31 12:00:00 +0000 UTC End of April: 2021-05-01 12:00:00 +0000 UTC End of June: 2021-07-01 12:00:00 +0000 UTC
🤔 🤔 🤔 Что -то не так ….. И именно это произошло на производстве 31 мая 2021 года в моем проекте. Этот кусок кода сломал производство. Забавно, потому что это было сломано только на один день. И в ближайшие несколько дней, до конца июля, он снова будет работать нормально.
Такое поведение Добавить
был совершенно неожиданным для меня. Я хотел обвинить это на это, но … Я могу только винить себя 😅, потому что в Документация метода добавления мы можем найти:
AddDate нормализует свой результат так же, как и дата, например, добавление одного месяца к 31 октября доходности 1 декабря, нормированную форму за 31 ноября.
Не то, что я ожидал от своего опыта с Python и C# 🤷 ♂️ Но задокументировано. Так – Моя вина 😕
Вынос
В конце, 3 вывода для вас и меня с будущего:
- Чтение документации может быть полезно 😄 Jakob ☘ \ u0000@jcsrb6 часов отладки может сэкономить 5 минут чтения документации12:38 – 12 мая 2021 г.
- Напишите тесты для кромков.
- Даты обработки в мире программирования – сложная работа.
PostScriptum – TypeScript
TypeScript делает то же самое, что и Go.
const endOfMay: Date = new Date(2021, 4, 31, 12, 0, 0, 0); // months are starting from 0 here 🤦 console.log(`End of May: ${endOfMay}`); const endOfApril = new Date(endOfMay); endOfApril.setMonth(endOfMay.getMonth() - 1); console.log(`End of April: ${endOfApril}`); const endOfJune = new Date(endOfMay); endOfJune.setMonth(endOfMay.getMonth() + 1); console.log(`End of June: ${endOfJune}`);
Выход:
End of May: Mon May 31 2021 12:00:00 GMT+0200 (Central European Summer Time) End of April: Sat May 01 2021 12:00:00 GMT+0200 (Central European Summer Time) End of June: Thu Jul 01 2021 12:00:00 GMT+0200 (Central European Summer Time)
но Dayjs Обрабатывает это отлично.
import dayjs from "dayjs"; const endOfMayDate = new Date(2021, 4, 31, 12, 0, 0, 0); const endOfMay = dayjs(endOfMayDate); console.log(`End of May: ${endOfMay}`); const endOfApril = dayjs(endOfMayDate).add(-1, "month"); console.log(`End of April: ${endOfApril}`); const endOfJune = dayjs(endOfMayDate).add(1, "month"); console.log(`End of June: ${endOfJune}`);
Выход:
End of May: Mon, 31 May 2021 10:00:00 GMT End of April: Fri, 30 Apr 2021 10:00:00 GMT End of June: Wed, 30 Jun 2021 10:00:00 GMT
Оригинал: “https://dev.to/nordcloud/how-a-calculation-of-previous-month-in-golang-can-break-production-1ppi”