Разбор полуночи как полуночи без потери дня в C # - PullRequest
0 голосов
/ 28 августа 2018

C # даты будут концом меня.

В WebAPI мне нужно проанализировать некоторые даты, отправленные с устройства, в следующем формате: 1944-12-12T00: 00: 00,000 + 10: 30

Моя цель - разобрать его, чтобы у меня была правильная дата, то есть 12.12.1944. Это продолжает отбрасывать это назад к 12.11.1944. Итак, явно вычитая смещение. Но я не понимаю почему. Полночь 12 декабря 1944 года - это момент времени. Почему его нельзя просто проанализировать, и в итоге вы получите Datetime, отражающее это.

Во всяком случае, вот код, который я пытался использовать:

class Program
{
    private static string AppFormatForParsing = "yyyy-MM-ddTHH:mm:ss.fffzzz"; // e.g. "2018-03-29T09:52:46.544+10:30"

    static void Main(string[] args)
    {
        string aDate = "1944-12-12T00:00:00.000+11:00";

        DateTime? d = TryParseExactDateTime(aDate)?.ToLocalTime();

        Console.ReadLine();
    }

    public static DateTime? TryParseExactDateTime(string source)
    {
        if (DateTime.TryParseExact(source, AppFormatForParsing, CultureInfo.InvariantCulture, DateTimeStyles.None, out var parsedDate))
        {
            return new DateTime(parsedDate.Ticks, DateTimeKind.Utc);
        }

        return null;
    }
}

Это, по крайней мере, дает мне правильный день. Но проверка DateTime показывает значение в свойстве часа, равное 9. Но это полночь!

Если кто-нибудь знает, как я могу разобрать полночь как полночь, это будет очень ценно.

Ответы [ 3 ]

0 голосов
/ 28 августа 2018

Когда вы пишете код ниже, это означает полночь 1944-12-12 в UTC + 11: 00 вперед

string aDate = "1944-12-12T00: 00: 00.000 + 11: 00";

Вместо этого удалите часовой пояс из формата и целевую строку анализа

class Program
{
    private static string AppFormatForParsing = "yyyy-MM-ddTHH:mm:ss.fff"; // e.g. "2018-03-29T09:52:46.544+10:30"

    static void Main(string[] args)
    {
        string aDate = "1944-12-12T00:00:00.000";

        DateTime? d = TryParseExactDateTime(aDate)?.ToLocalTime();

        Console.ReadLine();
    }

    public static DateTime? TryParseExactDateTime(string source)
    {
            DateTime parsedDate;

            if (DateTime.TryParseExact(source, AppFormatForParsing, CultureInfo.InvariantCulture, DateTimeStyles.None, out parsedDate))
            {
                return parsedDate;
            }

            return null;
    }
}

Если позже вы захотите добавить разницу, вы можете добавить ее или изменить часовой пояс

0 голосов
/ 29 августа 2018

Вы зациклены на полуночи, но aDate не относится к моменту времени, который является полуночным UTC. Ваши человеческие глаза читают первую часть строки и видят «1944-12-12», которая является только частью строки. Это заставляет вас ошибочно думать, что рассматриваемый день - 12 декабря 1944 года по Гринвичу. Но фактический момент времени , на который ссылаются , составляет 13:00 11 декабря 1944 года в 13:00. Здесь нужно кое-что дать: либо вы принимаете, что синтаксический анализ выполнен правильно, а правильный день - 11 декабря, либо вы преобразовываете входную строку, чтобы ссылаться на другой момент времени.

Поскольку все устройства отправляют строку в формате туда и обратно (см. ISO 8601 ), вы можете ослабить строгость формата ввода и использовать TryParse. Это позволило бы строки, такие как:

  • 1944-12-12T00: 00: 00,000 + 11: 00
  • 1944-12-11T13: 00: 00.000Z
  • 1944-12-11T00: 00: 00Z
  • 1944-12-11Z

Кстати, первые 2 строки:

  • 1944-12- 12 T00: 00: 00,000 + 11: 00
  • 1944-12- 11 T13: 00: 00.000Z

Обратитесь к тому же моменту времени . Когда строка написана с Z, вы ясно видите, что рассматриваемый день - 11 декабря. Разница между двумя при разборе состоит в том, что первая строка анализирует с DateTimeKind of Local, а вторая строка с Kind of Utc.

Как вы возвращаете DateTime, немного неловко. Было бы проще просто вернуть parsedDate.ToUniversalTime(). Это позволяет избежать любых локальных проблем людей, выполняющих код в разных часовых поясах и видящих разное время, потому что они смотрят на местное время вместо Utc.

Если у вас есть объект DateTime и вы хотите видеть только соответствующий день, т. Е. Сфокусироваться на полуночи этого дня, вы должны использовать свойство DateTime.Date.

Если вы абсолютно настаиваете на преобразовании входной строки времени в неправильную полночь, вы можете использовать простой метод, такой как:

private static string MutateToMidnight(string source)
{
    var pieces = source.Split(new char[] { 'T' });
    if (pieces.Length == 0 && pieces[0].EndsWith("Z", StringComparison.InvariantCultureIgnoreCase))
    {
        return pieces[0];
    }
    return pieces[0] + "Z";
}

Как упоминалось ранее, вы можете использовать TryParse, чтобы приспособить вариации к формату туда и обратно. Вот одна имплементация:

public static DateTime? TryParseDateTime(string source)
{
    if (DateTime.TryParse(source, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var parsedDate))
    {
        return parsedDate.ToUniversalTime(); // .Date;
    }
    return null;
}

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

0 голосов
/ 28 августа 2018

вы должны использовать DateTimeOffset для правильного разбора

    public static DateTimeOffset? TryParseExactDateTime(string source)
    {
        DateTimeOffset parsedDate;

        if (DateTimeOffset.TryParseExact(source, AppFormatForParsing, CultureInfo.InvariantCulture, DateTimeStyles.None, out parsedDate))
        {
            return new DateTimeOffset(parsedDate.DateTime);
        }

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