简体   繁体   中英

How to Convert DateTime.Now in 0 to 1 decimal format in c#

I would like to convert the current time to a decimal representing a fraction of the day. For example, if the day starts at 0, then 12:00 PM should be 0.5.

I need to send that value to an API, and it needs to be in that format. ie

"LAST_PRINT_TIME":0.22020833"

Depending on the precision requirements of your result, this may help you:

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

now.Minute / 60d calculates the fraction of the current hour (so if the time is XX:15 PM this will give 0.25). This is then added to the current hour. This value is then divided by 24 to obtain the final result.

For example, 3:45 PM would go as follows: (15 + 45 / 60) / 24) => (15 + 0.75) / 24 => 15.75 / 24 => 0.65625

So 3:45 PM, which is 15.75 hours into the day, would be 0.65625 (or 65.625%) of the day.


Or, as @madreflection mentioned in a comment, you could use .ToOADate() as well. In this case, you could do something like:

DateTime now = DateTime.Now;
double dayFraction = now.ToOADate() - now.Date.ToOADate();

This is one of those problems that seems deceptively simple, but the solution is actually much more complex than you would think.

The complexities arise from the nature of local time, whose rules are defined by time zones . Many time zones have transitions that occur either regularly (such as for daylight saving time ), or irregularly (such as for changes in standard time).

As such, one needs to consider:

  • Could the day be shorter or longer than 24 hours?
    • For example, in most of the US the start of DST is at 2:00 AM, and on that day there are 23 hours in the day because the hour from 2:00 to 2:59 is skipped. At the end of DST, also at 2:00 AM in the US, the hour from 1:00 through 1:59 is repeated, creating 25 hours in that day.
  • Could the day start or stop at a time other than midnight?

Learn more in Falsehoods programmers believe about time .

Consider using the following approach to overcome these real-world considerations.

First, define some helper functions to do most of the work. They are not specific to a particular point in time or a particular time zone.

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));
}

With those defined, you can now get an answer to your question with regard to "now" in the local time zone.

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

However - Though this is the correct answer of "what fraction of the day is it", keep in mind it may be more important to align with what the receiving API expects, even if not exactly correct. In other words, if 12:00 should always be 0.5 , even when it's not exactly at the midpoint of the day, then use elmer007's approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM