HuBeZa
HuBeZa

Reputation: 4761

Convert TimeSpan.TotalMilliseconds to long

I have some DateTime variable, and I want to use System.Threading.Timer to wait until this time arrive. If time is in the past I want the timer to tick immediately.

The problem is TimeSpan.TotalMilliseconds is double and timer due time biggest type islong.

I've tried to max the due-time to long.MaxValue using this code:

DateTime someUtcTime;
// Max due time to long.MaxValue
double doubleDueTime = Math.Min(
    (double)long.MaxValue,
    someUtcTime.Subtract(DateTime.UtcNow).TotalMilliseconds);

// Avoid negative numbers
long dueTime = Math.Max(0L, (long)doubleDueTime);

_timer.Change(dueTime, System.Threading.Timeout.Infinite);

but it turns out that casting long.MaxValue to double and back to long result a negative number (in unchecked code of curse). plz send me teh codez.


Edit: apparently, no matter which of Timer.Change overload you use, they are all limited to 4294967294 (UInt32.MaxValue - 1) milliseconds.


Solution:

cover both extreme cases (someUtcTime = DateTime.MaxValue; UtcNow = DateTime.MinValue; and vice versa).

const uint MAX_SUPPORTED_TIMEOUT = uint.MaxValue - 1; //0xfffffffe

DateTime someUtcTime;
double doubleDueTime = (someUtcTime - DateTime.UtcNow).TotalMilliseconds;

// Avoid negative numbers
doubleDueTime = Math.Max(0d, doubleDueTime);

// Max due time to uint.MaxValue - 1
uint dueTime = (uint)Math.Min(MAX_SUPPORTED_TIMEOUT, doubleDueTime);

Upvotes: 4

Views: 14434

Answers (4)

Marino Šimić
Marino Šimić

Reputation: 7342

Timespan timespan = someUtcTime.Subtract(DateTime.UtcNow);
long time = timespan.TotalMilliseconds <= long.MaxValue ? (long)timespan.TotalMilliseconds : -1;

if (time == -1) {
 sorry.nocando();
}
else {
 just.doit();
}

BTW: with a long millisecond you can have a timespan of 292471208 years, I don't think your code will be used by then. There is possibility that the sun will already have expanded past mars and earth is no more :D

Upvotes: 2

Gabe
Gabe

Reputation: 86718

Since (DateTime.MaxValue - DateTime.MinValue).TotalMilliseconds is 315537897600000 and long.MaxValue is 9223372036854775807 (long can represent a value 4 orders of magnitude larger than the largest possible number of milliseconds between any two DateTime values), you can never have a time too far in the future.

This will suffice:

DateTime someUtcTime;
// Max due time to long.MaxValue
double doubleDueTime = (someUtcTime - DateTime.UtcNow).TotalMilliseconds;

// Avoid negative numbers
long dueTime = Math.Max(0L, (long)doubleDueTime);

_timer.Change(dueTime, System.Threading.Timeout.Infinite);

Upvotes: 4

Mitch Wheat
Mitch Wheat

Reputation: 300529

Timers are designed to wait for intervals (typically shorter than 24 hours).

What is your intended use? A scheduler would typically have a list of events/tasks, and periodically every minute (maybe every second) check to see if any tasks need to be fired.

Perhaps something like Quartz.Net might be appropriate?

Upvotes: 0

M.A. Hanin
M.A. Hanin

Reputation: 8074

Maybe just work with the Ticks property (Ticks are Long) and multiply by TimeSpan.TicksPerMillisecond (constant, 10,000 ticks per millisecond).

Upvotes: 4

Related Questions