Преобразование DateTime для HubSpot API не работает - PullRequest
0 голосов
/ 23 апреля 2019

Я загружаю значения даты / времени в систему HubSpot CRM через их API.Для значений даты / времени для HS API требуется формат UNIX, который составляет миллисекунды с начала эпохи (01.01.1970 12:00 AM). [HubSpot docs: https://developers.hubspot.com/docs/faq/how-should-timestamps-be-formatted-for-hubspots-apis]

Но мои даты отображаются неправильно.Я извлекаю даты из базы данных SQL, которая находится в EST, и выполняю следующее преобразование:

string dbValue = "2019-02-03 00:00:00";
DateTime dt = Convert.ToDateTime(dbValue);
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
long apiValue = Convert.ToInt64(dt.Subtract(epoch).TotalMilliseconds);

Однако в HubSpot поле даты показывает 2/2/2019.Часовой пояс в HubSpot установлен на UTC -4 по восточному времени.

Похоже, что есть какая-то проблема с конвертацией, но я не знаю, что делать, чтобы ее исправить.Я пытался использовать DateTime.SpecifiyKind, чтобы явно установить dt в локальный режим перед преобразованием в long:

dt = DateTime.SpecifyKind(dt, System.DateTimeKind.Local);

Но это тоже не сработало.Я попытался сделать базовый тест:

var dt1 = new DateTime(2019, 4, 1, 12, 0, 0, DateTimeKind.Local);
var dt2 = new DateTime(2019, 4, 1, 12, 0, 0, DateTimeKind.Utc);
Console.WriteLine(dt1.Subtract(dt2).TotalSeconds);

Но результат был 0.Я нахожусь в КНТ, и я ожидал разницу в 5 часов.Я чувствую, что мне не хватает какой-то фундаментальной концепции о том, как DateTimes работает в C #.

1 Ответ

2 голосов
/ 23 апреля 2019

Несколько вещей:

  • Вычитание DateTime значений не учитывает DateTimeKind.

  • .NET Framework 4.6 ивыше есть встроенные функции преобразования в / из времени Unix в класс DateTimeOffset, так что вам вообще не нужно ничего вычитать.

  • Когда вы говорите EST илиCST, я предполагаю, что вы имели в виду восточное время США или центральное время США.Помните, что из-за перехода на летнее время, EDT или CDT могут применяться к некоторым вашим значениям.

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

    DateTime dt = (DateTime) dataReader("field");
    

    (Если вы используете Entity Framework или какой-либо другой ORM, то эта часть будет обработана для вас.)

  • Неважно, в каком часовом поясе SQL Server расположен в. Это имеет значение, скорее, в каком часовом поясе должен отображаться dbValue.Рекомендуется сохранять время в единицах UTC, и в этом случае часовой пояс сервера не должен иметь значения.

  • Если дата и время, хранящиеся на вашем сервере SQL, на самом деле в формате UTC, то выможно просто сделать это:

    long apiValue = new DateTimeOffset(dt, TimeSpan.Zero).ToUnixTimeMilliseconds();
    
  • Если дата и время, хранящиеся на вашем сервере SQL, действительно соответствуют восточному поясному времени США, вам сначала нужно будет выполнить преобразование из восточного времени в UTC:

    TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
    DateTime utc = TimeZoneInfo.ConvertTimeToUtc(dt, tz);
    long apiValue = new DateTimeOffset(utc).ToUnixTimeMilliseconds();
    
    • Обратите внимание, что идентификатор часового пояса Windows, равный "Eastern Standard Time", представляет восточное время США, включая EDT, когда это применимо, несмотря на наличие слова "Стандарт" в середине.

    • Если вы работаете в .NET Core на платформе, отличной от Windows, вместо этого введите "America/New_York".(И если вам нужно писать для межплатформенной отказоустойчивости, используйте мою библиотеку TimeZoneConverter .)

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

    long apiValue = new DateTimeOffset(dt).ToUnixTimeMilliseconds();
    

    Это работаеттолько если dt.Kind равно DateTimeKind.Unspecified или DateTimeKind.Local, как тогда будет применяться местный часовой пояс.Но опять же, я бы рекомендовал против этого.

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