Форматирование времени Голанга для Azure SDK

Рассмотрим следующий голанг

today :=  time.Now().Format("2006-01-02T03:04:05.9999999Z")
t, _ := time.Parse(time.RFC3339Nano, today)

Почему это не эквивалентно гораздо более простому

t := time.Now() 

?

Я хотел бы подтвердить, является ли приведенный выше код эквивалентным, как я считаю, или почему это не так, исходя из моего текущего опыта. Я также предоставляю дополнительный контекст относительно того, что я пытался.

Мой полный код репозитория здесь, на GitHub в файле main.go. Однако для ответа на этот вопрос давайте сосредоточимся на фрагменте кода, представленном ниже.

sasToken, err := client.ListAccountSAS(
    ctx, resourceGroupName, storageAccountName, armstorage.AccountSasParameters{
    KeyToSign:              to.Ptr("key1"),
    SharedAccessExpiryTime: to.Ptr(func() time.Time { 
        t, _ := time.Parse(time.RFC3339Nano, tomorrow); return t }()),
    Permissions:            to.Ptr(armstorage.PermissionsR),
    Protocols:              to.Ptr(armstorage.HTTPProtocolHTTPSHTTP),
    ResourceTypes:          to.Ptr(armstorage.SignedResourceTypesS),
    Services:               to.Ptr(armstorage.ServicesB),
    SharedAccessStartTime:  to.Ptr(func() time.Time { 
        t, _ := time.Parse(time.RFC3339Nano, today); return t }()),
}, nil)

В настоящее время этот код работает как положено. Однако , когда я упрощаю последнюю строку до t := time.Now(), это приводит к ошибке (показано в Выполнить задание в Github Actions).

today 2023-09-18T07:54:42.6314723Z should be formatted as 2023-09-16T11:42:03.1567373Z
tomorrow 2023-09-19T07:54:42.6314723Z should be formattes as 2023-09-17T11:42:03.1567373Z
2023/09/18 07:54:43 POST https://management.azure.com/subscriptions/***/resourceGroups/go-azure-sdk/providers/Microsoft.Storage/storageAccounts/golangazure/ListAccountSas
--------------------------------------------------------------------------------
RESPONSE 400: 400 Bad Request
ERROR CODE: InvalidValuesForRequestParameters
--------------------------------------------------------------------------------
{
  "error": {
    "code": "InvalidValuesForRequestParameters",
    "message": "Values for request parameters are invalid: signedStart."
  }
}
--------------------------------------------------------------------------------
exit status 1

Это заставило меня задаться вопросом, почему эквивалентность не имеет места, вопреки моим первоначальным ожиданиям.

Какая у вас ошибка?

derpirscher 18.09.2023 09:48

@derpirscher Спасибо! Дайте мне несколько минут, я внесу изменения в код github, чтобы мы могли увидеть ошибку в журнале действий github (и я также обновлю вопрос)

Giulio 18.09.2023 09:50
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
Как установить LAMP Stack 1/2 на Azure Linux VM
Как установить LAMP Stack 1/2 на Azure Linux VM
В дополнение к нашему предыдущему сообщению о намерении Azure прекратить поддержку Azure Database для MySQL в качестве единого сервера после 16...
3
2
71
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Этот API ожидает, что время будет округлено до секунды. Итак, попробуйте что-то вроде:

...
            SharedAccessExpiryTime: to.Ptr(expiryTime.Round(time.Second)),
...
            SharedAccessStartTime:  to.Ptr(startTime.Round(time.Second)),
...

Да, проверено, я подтверждаю, что это работает, спасибо, но, прежде чем принять это, пожалуйста, я все еще не понимаю, почему мой исходный код работал без округления до секунды и почему эта эквивалентность не соблюдается.

Giulio 18.09.2023 10:13

какую версию API вы используете? возможно, это проблема со старым API. Рассмотрим последнюю версию кода от 01.01.2023, обратитесь к примеру кода, который вы вставили Learn.microsoft.com/en-us/rest/api/storagerp/storage-account‌​s/…

Matteo 18.09.2023 10:17

мой go.mod здесь github.com/giuliohome-org/go-azure/blob/main/go.mod

Giulio 18.09.2023 10:18

если вы проверите из пользовательского интерфейса, максимальная точность, которую вы можете установить, равна second

Matteo 18.09.2023 10:18

конечно, я уже исправил код по вашему предложению, я просто хочу понять, что происходит с точки зрения Голанга, прежде чем закрыть эту тему. (кстати, последнее UTC() не имеет значения)

Giulio 18.09.2023 10:19

Теперь я понимаю, что с точки зрения кода Голанга основная проблема сводится к концепции монотонного чтения часов:

Время возвращается по времени. Теперь содержит монотонное показание часов.

Включение монотонного показания часов — это то, что может вызвать проблемы в определенных сценариях, возможно, из-за некоторой внутренней интерпретации параметра. Однако при использовании функции time.Parse такого монотонного показания часов нет.

Стоит отметить, что, поскольку монотонное чтение часов не имеет смысла вне текущего процесса, различные функции и методы в пакете Go time обрабатывают его по-разному. Такие функции, как t.Round(d), удаляют монотонные показания часов из их результатов. Именно из-за такого поведения принятый ответ работает, поскольку он использует такие функции для достижения желаемого результата.

Редактировать

Я также определил, где, скорее всего, заключается проблема в исходном коде SDK. Проблема заключается в форматах времени, используемых SDK, а именно:

var timeFormats = []string{
    "2006-01-02T15:04:05.0000000Z",
    TimeFormat,
    "2006-01-02T15:04Z",
    "2006-01-02",
}

Важнейшей деталью здесь является то, что первый формат времени содержит только 7 десятичных знаков. Это объясняет, почему мне пришлось использовать Format("2006-01-02T03:04:05.9999999Z") вместо более простого Format(time.RFC3339Nano).

В их документации о политике доступа указаны принятые форматы ISO 8601 UTC. В нем упоминается:

Если значение времени включает секунды, оно также может дополнительно включать до 7 десятичных цифр дробных секунд по шаблону чч:мм:сс[.f{1,7}]. Этот шаблон поддерживается API-интерфейсами хранилища Azure, инструментами и клиентскими библиотеками.

Следовательно, Round(time.Microsecond) по-прежнему будет работать, но попытка округления с помощью Round(time.Nanosecond) потерпит неудачу.

хороший улов @Джулио!!!!

Matteo 18.09.2023 16:06

@Matteo еще раз спасибо за помощь и решение. Собственно, это и имеет смысл сделать.

Giulio 18.09.2023 16:16

Другие вопросы по теме