4

I need to perform some calculations on times of days in 24 hours formatting in an application using schedules. For example, 17h + 12h = 5h. I tried to create my own Time struct and wrap around TimeSpan or DateTime. It's working ok but I'm getting stuck with the formatting to be done in ToString.

Indeed, I of course want my struct to be able to work under any culture. At first I was thinking of delegating the formatting to a DateTime struct and skip all custom formatting that are not strictly time-related. I can't delegate this task to a TimeSpan because it doesn't handle AM/PM used in some cultures for example. For example, in my Time struct I wrote:

public string Format(string format, IFormatProvider provider)
{
    return TimeFormat.Format(this, format, DateTimeFormatInfo.GetInstance(provider), provider);
}

// ...

internal class TimeFormat
{
    internal string Format(Time time, string format, DateTimeFormatInfo dtfi, IFormatProvider provider)
    {
        DateTime dt = new DateTime(DateTime.MinValue, 1, 1, time.Hours, time.Minutes, time.Seconds, time.Milliseconds);

        /* Here I am checking what the 'format' string is made of 
        and filter-out anything that is not strictly-time related. */

        return dt.Format(format, provider);
    }
}

I had a look at how the ToString method of the DateTime struct is implemented into mscorlib. And waow... So many stuffs to take into account. I wanted to more or less rewrite what was in it but keeping only what is time-related but everything's mixed up in this and not easy to understand. And I noticed some definitely not straightforward stuffs to handle also such as Hebrew formatting etc. It would take me way more time than I was expecting to rewrite all this! Especially I don't want to do it without understanding clearly what I'm doing.

So to sum up:

  • How can I create an "all cultures compliant" formatting of time of the day?
  • One level above, am I handling the problem correctly using wrappers of DateTime or TimeSpan? I can't use directly a TimeSpan: It's working with negative times (I'm using modulos to have times strictly between 0 and 23:59:59.999), it doesn't handle AM/PM in some cultures, it uses Days. For me, a 'time of the day' is different from a 'span of time'.
  • I don't need to handle time zone or DST, nor leap second as I am in a calendar agnostic context but I want to be able to handle localized formatting of time of the day. (using 'H' (or any Hebrew, Chinese, Tamil or Russian character) instead of ':' or AM/PM instead for 24-hour format for example).

Any hint or help pointing me to some libraries or tutorials will be helpful!

I had a look at this post before asking this question and took a look at this library also but it looks too complex regarding what I want to achieve.

Community
  • 1
  • 1
Guillaume
  • 1,782
  • 1
  • 25
  • 42

1 Answers1

4

(I realize this is a plug for my own project, but hopefully folks will see it's entirely relevant :)

Any hint or help pointing me to some libraries or tutorials will be helpful!

I'm the main developer for the Noda Time library, which should do most of what you want. See the user guide for initial information - and feel free to ask more questions either here or on the mailing list.

The type you want is LocalTime.

And yes, you're right about both DateTime and TimeSpan being inappropriate here, and also that the formatting/parsing is complicated :)

In Noda Time you can use the ToString methods as with the normal BCL types, and there are currently static Parse/TryParse/ParseExact/TryParseExact methods - but those may well vanish this evening :) Instead, you should use a LocalTimePattern: define the pattern once (per format and culture), and then use it for both formatting and parsing.

In terms of formatting and parsing, you need to be very clear about what you need. Noda Time piggy-backs onto the BCL for things like what the AM/PM designators are, etc. The fact that you're only dealing with time-of-day makes it much simpler as there aren't month/day names (and different calendars) to worry about. You can use the t pattern for "short" and T for "long" for a particular culture - or specify a custom pattern. Custom patterns are generally more useful for machine-to-machine communication; standard ones are more useful for user-oriented formatting.

(Currently you have to "know" that the t and T patterns exist - although they're documented in the user guide, of course. At some point I'll create methods to make this simpler...)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I'll take a deeper look at your library – Guillaume Jul 22 '12 at 08:26
  • @Guillaume I've been using `NodaTime` for only a short while and have barely scratched the surface of what it does, but the presence of objects like `LocalTime` and `LocalDate` make it very worthwhile. – psubsee2003 Jul 22 '12 at 08:48
  • Updated link for [Noda Time](https://nodatime.org/) library and documentation. – Doug Knudsen Oct 05 '20 at 22:42
  • 1
    @DougKnudsen: I've updated the post now. In future, please feel free to edit the post directly (which will currently end up as a suggestion). – Jon Skeet Oct 06 '20 at 06:29