简体   繁体   中英

How to calculate timespans using modular arithmetic?

This question is basically about representing modular arithmetic concept in code and using the modulo sign.

So recently I did a popup for SCCM installation, which should give user time to install an app, the client requuirements were to show the user a clock with the amount of time left to the installation (or let user install now as well). The amount of time on the clock that they wanted was 24 hours, plus whatever time is left to 4pm when the 24 hours have passed so:

program runs at 13:00 then the clock should display 24 +3 = 27 hours

when 16:00 it should be 24+24 which is 48 hours

when 22:00 it should be 24 + 18 which is 42 hours

Now I noticed that:

13 + 27 = 40

16 + 24 = 40

22 + 18 = 40

40 Modulo 24 = 16

So basically if I subtract the current time from 40 then I will be left with the difference:

40 - 13 = 27

40 - 16 = 24

40 - 22 = 18

So what I did is this:

//I need to make a timespan object which has 24 hours from current time + time left to the next 4pm

//The context is time to install, which user should see
Timespan TimeToInstall = new Timespan(23,59,59)

DateTime Now = DateTime.Now;
if (Now.Hour < 16)
{
    long TimeTo4 = (new TimeSpan(40, 0, 0).Ticks - Now.TimeOfDay.Ticks);
    TimeToInstall = TimeSpan.FromTicks(TimeTo4);
}
else
{

long TimeTo4 = (new TimeSpan(40, 0, 0).Ticks - Now.TimeOfDay.Ticks) + TimeGiven.Ticks;
TimeToInstall = TimeSpan.FromTicks(TimeTo4);

}

The problem with the above solution is that I know that it can be shorter, because when I subtract times times before 4 pm then I don't need to add 24 hours, if the run time is higher than or equal 4 pm then I need to add 24 hours. I have a rough idea how to refactor this in mathematics/pseudocode for example:

absolute(16-13) modulo 24 = 3

absolute(16-16) modulo 24 = 0 (24)

absolute(16-22) modulo 24 = 18

The question is how to do it in C# code to refactor this code? Please use any language you like, but I would be greatfull for C# example. Thank you guys

If you're looking for a shorter solution, how about this?

public static int HoursUntilDueTime(DateTime time)
{
    DateTime dueTime = (time + TimeSpan.FromHours(8)).Date + TimeSpan.FromHours(24 + 16);
    return (int)(0.5 + (dueTime - time).TotalHours);
}

Or if you want to pass in the target time (date part is ignored):

public static int HoursUntilDueTime(DateTime currentTime, DateTime targetTime)
{
    DateTime dueTime = (currentTime + TimeSpan.FromHours(24 - targetTime.Hour)).Date + TimeSpan.FromHours(24 + targetTime.Hour);
    return (int)(0.5 + (dueTime - currentTime).TotalHours);
}

Test code:

var targetTime = new DateTime(2000, 1, 1, 16, 00, 00);
Console.WriteLine(HoursUntilDueTime(new DateTime(2016, 1, 1, 13, 00, 00), targetTime));
Console.WriteLine(HoursUntilDueTime(new DateTime(2016, 1, 1, 16, 00, 00), targetTime));
Console.WriteLine(HoursUntilDueTime(new DateTime(2016, 1, 1, 22, 00, 00), targetTime));

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