Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert TimeSpan.TotalMilliseconds to long

Tags:

c#

.net

timespan

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);
like image 929
HuBeZa Avatar asked Feb 24 '23 13:02

HuBeZa


1 Answers

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);
like image 165
Gabe Avatar answered Feb 27 '23 03:02

Gabe