Как конвертировать DateTime.Now в десятичном формате от 0 до 1 в c # - PullRequest
1 голос
/ 25 октября 2019

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

Мне нужно отправить это значение в API, и оно должно быть в этом формате. т.е.

"LAST_PRINT_TIME":0.22020833"

Ответы [ 2 ]

3 голосов
/ 25 октября 2019

В зависимости от требований к точности вашего результата, это может помочь вам:

DateTime now = DateTime.Now;
double dayFraction = (now.Hour + now.Minute / 60d) / 24d;

now.Minute / 60d вычисляет долю текущего часа (поэтому, если время XX: 15 PM, это даст 0,25). Это затем добавляется к текущему часу. Это значение затем делится на 24 для получения окончательного результата.

Например, 15:45 будет выглядеть следующим образом: (15 + 45 / 60) / 24) => (15 + 0.75) / 24 => 15.75 / 24 => 0.65625

Итак, 3:45 вечера, то есть 15,75 часа в день, будут 0,65625 (или 65,625%) дня.


Или, как @madreflection упоминается в комментарии,Вы также можете использовать .ToOADate(). В этом случае вы можете сделать что-то вроде:

DateTime now = DateTime.Now;
double dayFraction = now.ToOADate() - now.Date.ToOADate();
0 голосов
/ 25 октября 2019

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

Сложности возникают из-за природы местного времени, правила которого определяются часовые пояса . Многие часовые пояса имеют переходы , которые происходят либо регулярно (например, для перехода на летнее время ), либо нерегулярно (например, для изменений в стандартном времени).

Как таковыенужно учитывать:

  • Может ли день быть короче или длиннее 24 часов?
    • Например, в большинстве США начало летнего времени наступает в 2:00 утра, и в этот день в день 23 часа, потому что пропущен час с 2:00 до 2:59. В конце летнего времени, также в 2:00 утра в США, час с 1:00 до 1:59 повторяется, создавая 25 часов в этот день.
  • Может лидень начинается или заканчивается в другое время, кроме полуночи?

Узнайте больше в Программисты лжи верят во время .

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

Во-первых,определить некоторые вспомогательные функции для выполнения большей части работы. Они не относятся к конкретному моменту времени или конкретному часовому поясу.

static double GetFractionOfDay(DateTimeOffset dto, TimeZoneInfo tz)
{
    // Get the start of the day, and the start of the next day
    DateTimeOffset startOfDay = GetStartOfDay(dto, tz);
    DateTimeOffset startOfNextDay = GetStartOfDay(startOfDay.AddDays(1), tz);

    // Calculate the length of the day.  It might not be 24 hours!
    TimeSpan lengthOfDay = startOfNextDay - startOfDay;

    // Now calculate the position within the day, and the fraction to return
    TimeSpan durationSinceStartOfDay = dto - startOfDay;
    return durationSinceStartOfDay / lengthOfDay;
}

static DateTimeOffset GetStartOfDay(DateTimeOffset dto, TimeZoneInfo tz)
{
    // Make sure we're in the correct time zone
    dto = TimeZoneInfo.ConvertTime(dto, tz);

    // Start by assuming a local midnight exists
    DateTime dt = dto.Date;

    // Handle days without a local midnight (these do exist in several time zones)
    if (tz.IsInvalidTime(dt))
    {
        // Advance by the transition gap.  This is usually 1 hour, but best not to hard-code that.
        TimeSpan[] offsets = { tz.GetUtcOffset(dt.AddDays(-1)), tz.GetUtcOffset(dt.AddDays(1)) };
        TimeSpan gap = offsets[1] - offsets[0];
        return new DateTimeOffset(dt.Add(gap), offsets[1]);
    }

    // Handle days with more than one midnight (it's possible, even if unlikely)
    if (tz.IsAmbiguousTime(dt))
    {
        // There's more than one.  Prefer the first one, since we want the beginning of the day.
        TimeSpan[] offsets = tz.GetAmbiguousTimeOffsets(dt);
        TimeSpan offset = offsets[0] > offsets[1] ? offsets[0] : offsets[1];
        return new DateTimeOffset(dt, offset);
    }

    // Clean case, just one local midnight and it does exist
    return new DateTimeOffset(dt, tz.GetUtcOffset(dt));
}

Определив их, вы теперь можете получить ответ на свой вопрос относительно «сейчас» в местном часовом поясе.

double dayFraction = GetFractionOfDay(DateTimeOffset.Now, TimeZoneInfo.Local);

Однако - Хотя это правильный ответ «какая это часть дня», имейте в виду, что может быть более важно выровнятьс тем, что ожидает API получения, даже если не совсем правильно. Другими словами, если 12:00 должно всегда быть 0.5, даже если это не совсем в середине дня, тогда используйте elmer007's подход.

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