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.
Related
I have a date value in windows console application like this one "P0Y0M0DT23H43M52.103S", and I want to parse this datetime value in c# to get minutes out of datetime value. It is easily done in Java by using new java.time.Duration.parse("P0Y0M0DT23H43M52.103S").toMinutes().
The documentation for Duration.parse(CharSequence text) says:
This will parse a textual representation of a duration, including the string produced by toString(). The formats accepted are based on the ISO-8601 duration format PnDTnHnMn.nS with days considered to be exactly 24 hours.
I am looking for a similar functionality in .net c# which can help me workout time in minutes accurately without having to run loop and split.
Thank you
You can use my Noda Time library and its Period type:
using NodaTime;
using NodaTime.Text;
var parseResult = PeriodPattern.NormalizingIso.Parse("P0Y0M0DT23H43M52.103S");
if (parseResult.Success)
{
Period period = parseResult.Value;
Console.WriteLine($"Success! Parsed to {period}");
}
Note that even in Java, parsing an ISO-8601 period as a Duration is somewhat inappropriate... durations should be fixed lengths of time whereas if you have an ISO-8601 period of something like "P1M", that isn't a fixed length of time (ditto years). That's why the Duration.parse method requires it to only have days, hours, minutes etc.
Use XmlConvert.ToTimeSpan():
TimeSpan duration = XmlConvert.ToTimeSpan("P0Y0M0DT23H43M52.103S");
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
I am extremely confused with this stopWatch.Elapsed property. It shows the time value in this format
I want to know what should I add in the end of this output. Is it ms (01:20:17.0550410ms) or just s (01:20:17.0550410s)?
And further more if I want to take only the msportion of this output and do some calculation with it which value should I take, is it .0550410 or 55.041? My questions might sound silly but I'm really confused!
please help.
The unit shown is "fractional parts of a second", to the 7th decimal place - i.e. to the 10-millionth of a second.
Since a millisecond is 0.001 seconds, your number of milliseconds is 55.041.
Now, as everyone else said, use stopWatch.Elapsed.TotalMilliseconds (to get all of the milliseconds) or stopWatch.Elapsed.Milliseconds (to get all of the milliseconds less than 1 second).
I am extremely confused with this stopWatch.Elapsed property. It shows the time value in this format
I'll begin at the beginning, just to make sure everything is understood.
Microsoft .Net framework designers have decided that all variables that store information derive from either a Class or a Struct(ture). Both of these base types have some defaults methods. One of these Methods for a ValueType (which I'll discuss below) is .ToString(). When you call the ToString() method on a Windows Runtime structure, it provides the default behavior for value types that don’t override ToString().
I will assuming you are talking about the System.Diagnostics.Stopwatch class. The documentation states:
A Stopwatch instance can measure elapsed time for one interval, or the total of elapsed time across multiple intervals. In a typical Stopwatch scenario, you call the Start method, then eventually call the Stop method, and then you check elapsed time using the Elapsed property.
Before we begin looking at the Properties of the Stopwatch, we need to understand that in order for the Stopwatch to work, there needs to be a way to store a Magnitude of Time (information). A Magnitude of Time in this case a numerical representation of the difference between two points in time; in this case the when the Stopwatch Starts and when the Stopwatch Ends. Microsoft .Net has created a structure called TimeSpan to store this value.
Taking a look at the documentation for the property Stopwatch.Elapsed it is of the type TimeSpan.
Since your screenshot appears to be in a console application, I'll assume the code (which should always be provided but isn't) is the following:
Console.Writeline("Took Time: " + stopWatch.Elapsed.ToString());
This code converts the TimeSpan into a string using the TimeSpan's .ToString() override:
So not passing a value to .ToString() is a null value which defaults to ("c") It's in the TimeSpan Format Strings:
So using your example:
01:20:17.0550410s
It should be obvious that 01 is hours, 20 is minutes, 17 is seconds and .0550410 are tenths of seconds (decisecond). Adding any string values at the end will most likely make no sense because all the numbers are of different time durations. The only way I think it would make sense if you wanted be more specific is to change it to:
01h 20m 17.0550410s
or
01h 20m 17s 055.0410ms
According to the documentation for TimeSpan:
A TimeSpan value can be represented as [-]d.hh:mm:ss.ff, where [...] ss is seconds, and ff is fractions of a second
So in your case, it is 17.0550410 seconds.
Elasped is a TimeSpan, what you're showing is the representation from writing it to the console (Same as calling .ToString() on any non string object), that representation is in hours:minutes:seconds.fraction of second. If you want to show this in a specific amount there are properties for this on the TimeSpan so instead of doing
Console.WriteLine(stopWatch.Elapsed);
You can do
Console.WriteLine(stopWatch.Elapsed.TotalMilliseconds);
A full example to clarify
Console.WriteLine(
"The timer ran for " + stopWatch.Elapsed.Hours + " Hours, "
+ stopWatch.Elapsed.Minutes + " Minutes and "
+ stopWatch.Elapsed.Seconds + ". this amounts to a total of "
+ stopWatch.Elapsed.TotalMilliseconds + " ms" );
It looks like you are just using the default .ToString() method of the Stopwatch.Elapsed property, which actually is a TimeSpan object. You can absolutely control the string formatting of this TimeSpan, as well as use numeric components of it for mathematical operations (rounding, adding, etc.). Please read this: Stopwatch.Elapsed Property
A quick search of 'c# stopwatch' returns the MSDN documentation showing that Stopwatch.Elapsed is a TimeSpan. Then a search on 'c# TimeSpan' returns the MSDN documentation showing that TimeSpan.ToString() returns a string with the following format: [-][d.]hh:mm:ss[.fffffff]. And that's just using google. Next time try doing some research before asking your question.
Assuming that you are interested in StopWatch.Elapsed, then...
In situations like this I find the documentation is often quite helpful.
It states that StopWatch.Elapsed returns
A read-only TimeSpan representing the total elapsed time measured by the current instance.
The documentation for TimeSpan states its many available properties, one of which is Milliseconds and another is TotalMilliseconds. According to the docs:
Milliseconds - Gets the milliseconds component of the time interval represented by the current TimeSpan structure.
whereas
TotalMilliseconds - Gets the value of the current TimeSpan structure expressed in whole and fractional milliseconds.
Other properties allow you to check Days, Hours, Minutes, Seconds etc. Please use the documentation as it saves everyone a lot of time and effort.
What should be the best way to calculate the time diff which is accurate upto the level of Microseconds. currently I am doing as follows:
((TimeSpan)(DateTime.Now - _perfClock)).TotalMilliseconds
Note: perfClock is DateTime (set prior to task)
Which is suppose to give accuracy upto Milliseconds, but in my case it is showing values ends with "000". like 8000,9000 etc...
This is forcing me to think that is just converting seconds to Milliseconds somewhere, instead of calculating diff in Milliseconds. (Possibly I am wrong somewhere in code above).
But what should be the recommended mechanism for accurate Time Diff calculation?
-Sumeet
The issue is not with TimeSpan, that is accurate down to ticks, which is 100 nanoseconds.
The issue is you are using DateTime.Now for your timer.
DateTime.Now is accurate to about 16ms i believe. as mentioned by V4Vendetta, you want to use Stopwatch if you need "high resolution" results. Stopwatch can provide you with ticks (long) or TimeSpan. use Timespan for easy manipulation (in your case, add/subtract).
Note also that Stopwatch provides a .IsHighResolution property, to see if you have a better accuracy than Datetime.Now (it's always true on PC iirc)
I don't know the context in which you are measuring time but it would be good to start of with Stopwatch and check your results.
Also worth a read Precise Measurement
Have you tried:
TimeSpan diff = DateTime.Now.Subtract(_perfClock);
I need to format the day time using QueryPerformanceCounter Win32 API.
The format, is: HH:mm:ss.ffffff , containing hours minuts seconds and microseconds.
I need to use THIS function, because another process (written in C) is using this function and the purpose is using the same function in both places.
Thanks
The System.Diagnostics.Stopwatch class uses QueryPerformanceCounter(), saves you from having to P/Invoke it.
You should not use QueryPerformanceCounter to determine time of day. It can only be used to determine an elapsed interval with a very high resolution as it returns the number of ticks that passed since the computer was last restarted.
As such, at best, you may only determine how many hours, minutes, and seconds have passed since a previous reading of QueryPerformanceCounter which must not have happened too long in the past.
In order to convert from ticks to seconds you need to determine the frequency (using QueryPerformanceFrequency) of the ticks on the computer you're running the QueryPerformanceCounter function and then divide your reading by that frequency:
// obtain frequency
long freq;
QueryPerformanceFrequency(freq);
// then obtain your first reading
long start_count;
long end_count;
QueryPerformanceCounter(start_count)
// .. do some work
// obatin your second reading
QueryPerformanceCounter(end_count);
// calculate time elapsed
long milliseconds_elapsed = (long)(((double)(end_count - start_count) / freq) * 1000);
// from here on you can format milliseconds_elapsed any way you need to
An alternative to the above example would be to use the TimeSpan structure available in .Net which has a constructor that takes ticks like so:
// then obtain your first reading
long start_count;
long end_count;
QueryPerformanceCounter(start_count)
// .. do some work
// obatin your second reading
QueryPerformanceCounter(end_count);
TimeSpan time_elapsed = new TimeSpan(end_count - start_count);
Console.WriteLine("Time Elapsed: " + time_elapsed.ToString());
Can use :
1) The System.Diagnostics.Stopwatch class uses QueryPerformanceCounter(), saves you from having to P/Invoke it.
2) Can use directly by importing from the Win32 dll . [DLLImport(Win32)] and the name ofthe function
Possibly I misunderstand the question, as for me none of the previous answers are relevant at all.
I had the problem (which sent me here): Given a value from QueryPerformanceCounter, because something out of my control specifies timestamps using that function, how can I convert these values to a normal date / time?
I figured that QueryPerformanceCounter returns the number of seconds since the system booted, multiplied (and extended in resolution) depending on QueryPerformanceFrequency.
Thus, the most simple solution is to get the current date/time, subtract the amount of seconds returned by QueryPerformanceCounter/QueryPerformanceFrequency, and then add the values you like to format as time of day.