Иллюстрация из «Путешествия с 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”