Issue when converting microseconds to datatimeoffset c# - c#

I am trying to convert microseconds to DateTime. Please find the code below,
long microSecs = 1632489907280; // Working
long microSecs = 1650391805000000 // Not working -- It has nanoseconds also.
DateTimeOffset utc = DateTimeOffset.FromUnixTimeMilliseconds(microSecs).UtcDateTime;
return utc.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
Anyone help me to resolve the issue?

Try using the following format:
yyyy-MM-ddTHH:mm:ss.ffffffZ
The format .fff is for milliseconds. Your example 1632489907280 is also in milliseconds, so it works fine. But the other case, instead of milliseconds is in microseconds, so the former format does not work anymore. You need 6 f symbols to deal with microseconds.

why first input is working and second input is not working?
There is no built-in method from DateTime class to process epoc microseconds
In your first example, 1632489907280 is within the milliseconds range, so DateTimeOffset.FromUnixTimeMilliseconds() considering 1632489907280 as milliseconds not microseconds.
In your second case, 1650391805000000 is greater than the max range of milliseconds.
From MSDN Documentation, DateTime.FromUnixTimeMilliseconds(milliseconds) throws an ArgumentOutOfRangeException if the
milliseconds is less than -62,135,596,800,000.
-or-
milliseconds is greater than 253,402,300,799,999.
To fix the error, convert your microseconds to milliseconds and then pass it to DateTime.FromUnixTimeMilliseconds(milliseconds).
Try below code,
public static string ProcessEpocTime(long microSecs)
{
//Convert microseconds to Milliseconds.
long milliSecs = (long)microSecs / 1000;
DateTimeOffset utc = DateTimeOffset.FromUnixTimeMilliseconds(milliSecs).UtcDateTime;
return utc.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
}
Note: This solution will work for valid microseconds value.
Try online

Related

Comparing the binary representation of DateTime in C#

I have a DateTime represented as long (8 bytes), that came from DateTime.ToBinary(), let's call it dateTimeBin. Is there an optimal way of dropping the Time information (I only care for the date) so I can compare it to a start of day? Lets say we have this sample value as a start of day.
DateTime startOfDay = new DateTime(2020,3,4,0,0,0);
long startOfDayBin = startOfDay.ToBinary();
I obviously know I can always convert to a DateTime object then get the date component. However, this operation is going to happen billions of times and every little performance tweak helps.
Is there an efficient way of extracting the Date info of dateTimeBin without converting it to DateTime? Or any arithmetic operation on the long that will return the date only?
Is there a way to match startOfDay (or startOfDayBin) and dateTimeBin if they have the same date components?
Is there a way to see if (dateTimeBin >= startOfDayBin), I don't think the long comparison is valid.
N.B. all the dates are UTC
Since you are working only with UTC dates - makes sense to use DateTime.Ticks instead of DateTime.ToBinary, because former has relatively clear meaning - number of ticks since epoch, just like the unix time, the only difference is unix time interval is second and not tick (where tick is 1/10.000.000 of a second), and epoch is midnight January 1st of 0001 year and not year 1970. While ToBinary only promises that you can restore original DateTime value back and that's it.
With ticks it's easy to extract time and date. To extract time, you need to remainder of division of ticks by number of ticks in a full day, so
long binTicks = myDateTime.Ticks;
long ticksInDay = 24L * 60 * 60 * 10_000_000;
long time = binTicks % ticksInDay;
You can then use convert that to TimeSpan:
var ts = TimeSpan.FromTicks(time);
for convenience, or use as is. The same with extracting only date: just substract time
long date = binTicks - (binTicks % ticksInDay);
Regular comparision (dateTimeBin >= startOfDayBin) in also valid for tick values.

Timespan in milliseconds to minutes and seconds only

I have a Timespan that is always in milliseconds, but I need to show the date in minutes and seconds only so that it's always "mm:ss". Even if there are hours in the timespan, the output string should contain only minutes and seconds.
For example, if there is a timespan of 02:40:30, it should get converted to 160:30.
Is there a way to achieve this?
Reed's answer is ALMOST correct, but not quite. For example, if timespan is 00:01:59, Reed's solution outputs "2:59" due to rounding by the F0 numeric format. Here's the correct implementation:
string output = string.Format("{0}:{1:00}",
(int)timespan.TotalMinutes, // <== Note the casting to int.
timespan.Seconds);
In C# 6, you can use string interpolation to reduce code:
var output = $"{(int)timespan.TotalMinutes}:{timespan.Seconds:00}";
You can format this yourself using the standard numeric format strings:
string output = string.Format("{0}:{1}", (int)timespan.TotalMinutes, timespan.Seconds);
I do it this way
timespan.ToString("mm\\:ss");
That is a pretty basic math problem.
Divide by 1000 to get total number of seconds.
Divide by 60 to get number of minutes.
Total seconds - (minutes * 60) = remaining seconds.

TimeSpan.Parse microsecond and millisecond spans

I am using a web service that return time spans in the following formats
300.43µs (microseconds)
212.675ms (milliseconds)
I want to be able to parse these to a TimeSpan object accurately. Currently I'm using TimeSpan.Parse but this fails on both occasions:
TimeSpan.Parse(json["time"].ToString());
// Exception: String was not recognized as a valid TimeSpan.
How can I parse these values?
Use regex to detect what do you have - microseconds or milliseconds. or just with simple check EndsWith
(\d*.\d*)µs // for microseconds
(\d*.\d*)ms // for milliseconds
And #Chris already wrote - that timespan doesn't let you to parse microseconds.
AFAIK the TimeSpan struct does not support parsing of units like that. You'll have to check and strip off the unit yourself.
For milliseconds then use FromMilliseconds. For microseconds either rescale the value to ms (FromMilliseconds accepts a double) or use FromTicks where each tick is 100 ns.

Getting Milliseconds elapsed between arbitrary date and Epoch time

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
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.
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.

Disparity between date/time calculations in C# versus Delphi

Delphi:
SecondsBetween(StrToDateTime('16/02/2009 11:25:34 p.m.'), StrToDateTime('1/01/2005 12:00:00 a.m.'));
130289133
C#:
TimeSpan span = DateTime.Parse("16/02/2009 11:25:34 p.m.").Subtract(DateTime.Parse("1/01/2005 12:00:00 a.m."));
130289134
It's not consistent either. Some dates will add up the same, ie..
TimeSpan span = DateTime.Parse("16/11/2011 11:25:43 p.m.").Subtract(DateTime.Parse("1/01/2005 12:00:00 a.m."));
SecondsBetween(StrToDateTime('16/11/2011 11:25:43 p.m.'), StrToDateTime('1/01/2005 12:00:00 a.m.'));
both give
216905143
The total amount of seconds is actually being used to encode data, and I'm trying to port the application to C#, so even one second completely throws everything off.
Can anybody explain the disparity? And is there a way to get c# to match delphi?
Edit: In response to suggestions that it might be leap second related: Both date ranges contain the same amount of leap seconds (2), so you would expect a mismatch for both. But instead we're seeing inconsistency
16/02/2009 - 1/01/2005 = Delphi and C# calculate a different total seconds
16/11/2011 - 1/01/2005 = They calculate the same total seconds
The issue it seems related to this QC 59310, the bug was fixed in Delphi XE.
One will likely deal with Leap Seconds. However, .NET does not as far as I'm aware.
You don't mention how you convert the c# TimeSpan into a number. The TotalSeconds property is a floating point value - perhaps it's a rounding problem in the double to int conversion?

Categories