Как удалить часть часового пояса из DateTime, чтобы оставить только локальную часть DateTime? (без разбора строк и манипуляций)

У меня вопрос, похожий на этот: Как удалить часовой пояс из DateTime в .NET Core, но я не хочу использовать какой-либо анализ на основе строк.

По сути, у меня есть события из разных мест мира, временные метки которых собраны с помощью DateTime.Now

Я хочу сообщать о событиях с соответствующими локальными временными метками создания (не utc).

Итак, учитывая, что каждая дата и время в основном представлена ​​следующим образом:
2024-05-08T17:31:53.9744487+03:00

Я хочу извлечь только 2024-05-08T17:31:53.9744487 в качестве DateTime, чтобы можно было сообщить местное время события.

Я не хочу выполнять какой-либо анализ строк, как в ответе выше (или какие-либо манипуляции со строками), поскольку они подвержены ошибкам.

Вот тестовый пример, который я хотел бы пройти:

[Fact]
public void DateTimeConversionTest()
{
    // Arrange
    var testDateTime = DateTime.Parse("2024-05-08T17:31:53.9744487+03:00");
    var expectedTimeString = "17:31:53";

    // Act
    var convertedDateTime = testDateTime; // convert DateTime to local DateTime here
    var convertedTimeString = convertedDateTime.ToString("HH:mm:ss");

    // Assert
    Assert.Equal(expectedTimeString, convertedTimeString);
}

Кажется, эту проблему на C# решить на удивление сложно, поскольку я не смог найти ничего работающего в Интернете.

Кто-нибудь знает, как это решить?

Обновлено: После объяснений Деррика и Гуру ниже я понимаю, что этот вопрос неверен, поскольку дата, проанализированная из строки, сразу теряет смещение часового пояса. Таким образом, решением было бы использовать DateTimeOffset вместо этого.

EDIT2: Для тех, кто борется с той же десериализацией System.Text.Json, получая DateTime в виде строки, такой как 2024-05-08T17:31:53.9744487+03:00, и пытаясь удалить часовой пояс, решением оказалось просто изменить тип свойства принимающего объекта с DateTime на DateTimeOffset. Затем System.Text.Json правильно десериализует его в DateTimeOffset, и тогда становятся возможными манипуляции DateTimeOffset, например получение DateTimeOffset.DateTime, что решает проблему удаления часового пояса.

Итак, предполагая, что этот класс:

public class MyEvent
{
    public string FullName { get; set; }
    public DateTime Created { get; set; }
    public DateTime CreatedUtc { get; set; }
}

меняется на это:

public class MyEvent
{
    public string FullName { get; set; }
    public DateTimeOffset Created { get; set; }
    public DateTime CreatedUtc { get; set; }
}

теперь это работает правильно: var myEvent = JsonSerializer.Deserialize<MyEvent>(json)

и мы можем использовать myEvent.Created.DateTime, чтобы получить DateTime без часового пояса.

«чтобы я мог сообщить местное время События». - а какое местное смещение? Не могли бы вы немного подробнее описать проблему? Какой результат вы получаете?

Guru Stron 08.05.2024 20:17

У вас есть смещение? Если да, создайте новый объект DateTimeOffset с вашим объектом даты и смещением как объект TimeSpan.

GH DevOps 08.05.2024 20:20

У меня нет смещения, но вся необходимая информация уже предоставлена ​​в DateTime. Я имею в виду, что вы можете визуально увидеть местную дату и время, глядя на него.

Tanuki 08.05.2024 20:23

Это местная дата и время, где расположен ваш сервер. Вам понадобится либо часовой пояс, либо смещение.

GH DevOps 08.05.2024 20:26
DateTime.Parse() возвращает локальную дату и время, часовой пояс на этот момент уже потерян, и вы не можете вернуть его, если только не всегда +03:00, и вы хотите жестко запрограммировать его?
Derrick Moeller 08.05.2024 20:28

В каком свойстве DateTime указано исходное местное время? testDateTime должно соответствовать местному времени сервера/приложения, на котором выполняется код.

Derrick Moeller 08.05.2024 20:54
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
125
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Если я вас правильно понял, вы можете использовать DateTimeOffset со свойством DateTimeOffset.DateTime:

На свойство DateTime не влияет значение свойства Offset.

var parsed = DateTimeOffset.Parse("2024-05-08T17:31:53.9744487+01:00");
var originalLocalDateTime = parsed.DateTime; // DateTimeKind.Unspecified

Учитывая тестовый пример, который я написал выше, как бы вы манипулировали testDateTime, чтобы сделать это?

Tanuki 08.05.2024 20:26

@Tanuki var testDateTime = DateTimeOffset.Parse(..), а затем его использование - var convertedTimeString = testDateTime.ToString("HH:mm:ss"); помогает мне.

Guru Stron 08.05.2024 20:27

Я имею в виду, если у вас уже есть переменная datetime, созданная следующим образом: var testDateTime = DateTime.Parse("2024-05-08T17:31:53.9744487+03:00"); как бы вы это сделали без синтаксического анализа или манипуляций со строками?

Tanuki 08.05.2024 20:31

@Tanuki - нет. Вот и все. DateTime не хранит информацию об исходном часовом поясе/смещении, поэтому, если вы не можете получить эту информацию из исходной строки (или каким-либо другим способом), вы ничего не сможете здесь сделать. По сути, вы здесь работаете с неправильной абстракцией.

Guru Stron 08.05.2024 20:33

Я не имеет для меня смысла. При просмотре строкового представления вы можете увидеть +03:00, и это именно то, что следует использовать. Почему это нельзя как-то использовать?

Tanuki 08.05.2024 20:38

@Tanuki, о каком именно строковом представлении ты говоришь? Тот, который отправляется на DateTime.Parse? Если да, оно используется для преобразования времени в местный часовой пояс (в основном, часовой пояс сервера, на котором вы работаете). Но это смещение не сохраняется типом.

Guru Stron 08.05.2024 20:40

+03:00 — это смещение UTC, поэтому можно получить правильную местную дату и время, удалив эти 03:00 часов. Никакого отдельного смещения не требуется.

Tanuki 08.05.2024 20:50

После вызова DateTime.Parse() ваш вновь возвращенный DateTime объект не содержит исходного смещения. Вы не сможете вернуть его обратно, если у вас есть только testDateTime.

Derrick Moeller 08.05.2024 20:52

@Tanuki еще раз, когда вы проанализируете дату и время, он обработает это смещение +03:00 и будет использовать его для преобразования строки даты и времени в местное время (сервер) с его смещением, если смещение вашего локального часового пояса соответствует значению в строке, то время, которое вы под рукой уже местное время.

Guru Stron 08.05.2024 20:54

@Tanuki, то есть мое текущее смещение TZ +03:00, так что твой тест для меня просто пройдет. Но если строка будет иметь другое смещение (например, +01:00) или мое смещение будет другим, то этого не произойдет, и невозможно получить +01:00 из самого проанализированного DateTime.

Guru Stron 08.05.2024 20:58

Теперь я понял, спасибо Деррику и Гуру за объяснения. Мой вопрос неверен в примере DateTime.Parse(). На самом деле мои данные поступают в виде строки Json, и смещение времени теряется во время преобразования строки в объект. Теперь я понимаю почему. Позвольте мне посмотреть, можно ли лучше изменить вопрос (или просто признать, что я спросил невозможное)

Tanuki 08.05.2024 21:03

@Tanuki звучит так, будто вы можете просто использовать DateTimeOffset вместо DateTime в своем объекте и все.

Guru Stron 08.05.2024 21:04

Да, это действительно похоже на решение. Мне нужно будет найти, как это сделать для STJ JsonSerializer.Deserialize, но это совсем другой вопрос/исследование. Спасибо вам за помощь.

Tanuki 08.05.2024 21:07

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