Grammatically correct uptime in C#

1.7k views Asked by At

I want to return a string, that is grammatically correct to display the current uptime. For example, 3 years, 7 months, 11 days, 1 hour, 16 minutes and zero seconds, meaning singular units should not be plural, and zero units should be plural, though zero shouldn't be display if it didn't occur yet (e.g., don't display years, months, etc., if it didn't occur yet)

Since the ticks method won't work beyond a month, I am using ManagementObject, but I am confused on how to do the datetime calculation and break down (I am very new to C# so I am making a utility that does a variety of functions so I can learn a variety of things.

this is what i have now, and it isn't a heck a lot...

any help is greatly appreciated.

        public string getUptime()
    {
        // this should be grammatically correct, meaning, 0 and greater than 1 should be plural, one should be singular
        // if it can count in realtime, all the better
        // in rare case, clipping can occur if the uptime is really, really huge

        // you need a function that stores the boot time in a global variable so it's executed once so repainting this won't slow things down with quer
        SelectQuery query = new SelectQuery("SELECT LastBootUpTime FROM Win32_OperatingSystem WHERE Primary='true'");
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
        foreach (ManagementObject mo in searcher.Get())
        {
            // this is the start time, do math to figure it out now, hoss
            DateTime boot = ManagementDateTimeConverter.ToDateTime(mo.Properties["LastBootUpTime"].Value.ToString());
            // or is it better to break up everything into days/hours/etc, i think its better to do that at the end before it gets returned
        }

        string now = DateTime.Now.ToShortDateString();







        return "3 years, 7 months, 11 days, 1 hour, 16 minutes and zero seconds";  // long string for testing label width
    }
2

There are 2 answers

0
Anderson Matos On

Searching internet I've found something that led me into these pseudo-classes. Might work...

class Utils
{

    public DateTime GetLastDateTime()
    {
        // Insert code here to return the last DateTime from your server.
        // Maybe from a database or file?

        // For now I'll just use the current DateTime:
        return DateTime.Now;
    }

    public CustomTimeSpan GetCurrentTimeSpan()
    {
        // You don't actually need this method. Just to expalin better...
        // Here you can get the diference (timespan) from one datetime to another:

        return new CustomTimeSpan(GetLastDateTime(), DateTime.Now);
    }

    public string FormatTimeSpan(CustomTimeSpan span)
    {
        // Now you can format your string to what you need, like:

        String.Format("{0} year{1}, {2} month{3}, {4} day{5}, {6} hour{7}, {8} minute{9} and {10} second{11}",
            span.Years, span.Years > 1 ? "s" : "",
            span.Months, span.Monts > 1 ? "s" : "",
            span.Days, span.Days > 1 ? "s" : "",
            span.Hours, span.Hours > 1 : "s" : "",
            span.Minutes, span.Minutes > 1 : "s" : "",
            span.Seconds, span.Seconds > 1 : "s" : "");
    }

}

class CustomTimeSpan : TimeSpan
{

    public int Years { get; private set; }
    public int Months { get; private set; }
    public int Days { get; private set; }
    public int Hours { get; private set; }
    public int Minutes { get; private set; }
    public int Seconds { get; private set; }

    public CustomTimeSpan ( DateTime originalDateTime, DateTime actualDateTime )
    {
        var span = actualDateTime - originalDateTime;

        this.Seconds = span.Seconds;
        this.Minutes = span.Minutes;
        this.Hours = span.Hours;

        // Now comes the tricky part: how to get the day, month and year part...
        var months = 12 * (actualDateTime.Year - originalDateTime.Year) + (actualDateTime.Month - originalDateTime.Month);
        int days = 0;

        if (actualDateTime.Day < originalDateTime.Day)
        {
            months--;
            days = GetDaysInMonth(originalDateTime.Year, originalDateTime.Month) - originalDateTime.Day + actualDateTime.Day;
        }
        else
        {
            days = actualDateTime.Day - originalDateTime.Day;
        }

        this.Years = months / 12;
        months -= years * 12;
        this.Months = months;
        this.Days = days;
    }


}

Credits from base-code to Bob Scola. How to calculate age using TimeSpan w/ .NET CF?

2
BrokenGlass On

Dont' convert to string - use the DateTime of the last reboot time you already have and compare it to the current time (DateTime.Now). Subtract the two and you get a TimeSpan:

TimeSpan upDuration = DateTime.Now - boot;

TimeSpan has properties Days, Hours, Minutes which you can now use to build up your string.