Рубрики
Без рубрики

Как расчет предыдущего месяца в Голанге может сломать производство

Иллюстрация из «Путешествия с Go», созданная Рене Френч. В одном из приложений, которые я … помечен Go, Csharp, Python, TypeScript.

Иллюстрация из «Путешествия с 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 вывода для вас и меня с будущего:

  1. Чтение документации может быть полезно 😄
    Jakob ☘ \ u0000
    @jcsrb
    6 часов отладки может сэкономить 5 минут чтения документации
    12:38 – 12 мая 2021 г.
  2. Напишите тесты для кромков.
  3. Даты обработки в мире программирования – сложная работа.

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”