Question

If I write a simple method to return the milliseconds between epoch time and DateTime.UtcNow, I get a proper answer. However, if I write a method to return the milliseconds between some arbitrary date and epoch time, the last three digits are always zero. 'Some arbitrary date' means that I pass in to the method the output of DateTime.Parse("arbitrary date string"). As near as I can make out, the DateTime object returned by .Parse is not returning all the significant digits.

Test method:

    static void GetMillis()
        {
            DateTime dUtc = DateTime.UtcNow;
            DateTime epoch = new DateTime(1970,1,1,0,0,0,DateTimeKind.Utc);
            double utcmillis = (dUtc - epoch).TotalMilliseconds;
            String timestamp = dUtc.ToString();
            DateTime arbitrary = (DateTime.Parse(timestamp));
            Console.WriteLine("Milliseconds between DateTime.UtcNow {0} \nand epoch time {1} are {2}", dUtc, epoch, utcmillis);
            Console.WriteLine("Milliseconds between arbitrary date {0} \nand epoch time {1} are {2}", arbitrary, epoch, (arbitrary - epoch).TotalMilliseconds);
        }

Output:

C:\src\vs\epochConverter\epochConverter\bin\Debug
{powem} [54] --> .\epochConverter.exe -debug
Milliseconds between DateTime.UtcNow 8/26/2012 11:12:31 PM
and epoch time 1/1/1970 12:00:00 AM are 1346022751385.8
Milliseconds between arbitrary date 8/26/2012 11:12:31 PM
and epoch time 1/1/1970 12:00:00 AM are 1346022751000

I don't know if I'm doing something grotesquely wrong or not understanding the math here. I've researched in MSDN and can't find anything relating to this difference. I really would like to be able to compute the millis as described -- is it possible?

Thanks.

mp

Was it helpful?

Solution

You want to examine the intermediate values of:

String timestamp = dUtc.ToString();

Just what it returns will depend on your local settings, but it'll be something like 8/26/2012 11:12:31, which is only accurate to the nearest second.

Parsing that of course gives a date-time with 0 milliseconds.

It is therefore correct that your milliseconds-since-epoch method has zeros at that point.

If however you did something like:

arbitrary = new DateTime(2012, 8, 26, 11, 12, 31, 123);

You'd get those 123 milliseconds influencing the result. You can also use a ToString and a ParseExact that includes fractions of a second, or a whole slew of other ways of obtaining a DateTime.

In all, your milliseconds-since-epoch worked perfectly, but your way of getting a date to test it was flawed.

OTHER TIPS

The default DateTime.ToString() format does not include the milliseconds and this is where the data is being lost; it happens before the Parse. To obtain the milliseconds in the string representation, use a custom format:

DateTime.UtcNow.ToString()
// -> 8/26/2012 11:37:24 PM
DateTime.Parse("8/26/2012 11:37:24 PM").Millisecond
// -> 0

DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffffffK") 
// -> 2012-08-26T23:41:17.3085938Z
DateTime.Parse("2012-08-26T23:41:17.3085938Z").Millisecond
// -> 308

See The Round-trip ("O", "o") Format Specifier to type less. Or, in this case, consider avoiding the conversion entirely :-)

The math is sound.

The math looks reasonable here. Don't forget there are 1000 milliseconds in a 1 second, so any date computation from an arbitrary time that does not include milliseconds vs an almost identical time that includes milliseconds will have an error of +/- 1000 milliseconds.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top