how to convert seconds in min:sec format - c#

how to convert seconds in Minute:Second format

A versatile version is to use TimeSpan like this:
var span = new TimeSpan(0, 0, seconds); //Or TimeSpan.FromSeconds(seconds); (see Jakob C´s answer)
var yourStr = string.Format("{0}:{1:00}",
(int)span.TotalMinutes,
span.Seconds);

int totalSeconds = 222;
int seconds = totalSeconds % 60;
int minutes = totalSeconds / 60;
string time = minutes + ":" + seconds;

Just for completeness I will add an answer using TimeSpan (works as of .NET 4.0):
int seconds = 1045;
var timespan = TimeSpan.FromSeconds(seconds);
Console.WriteLine(timespan.ToString(#"mm\:ss"));

Something like this:
string minSec = string.Format("{0}:{1:00}", seconds / 60, seconds % 60);
Note that that will ensure the seconds are always displayed as two digits, e.g. "2:05" for 125 seconds. The minutes aren't currently treated the same way, but of course they could be.
This doesn't deal well with negative numbers. If your seconds may be negative, you may want something like this:
string minSec = string.Format("{0}:{1:00}", seconds / 60,
(Math.Abs(seconds)) % 60);
Finally, will you always have less than an hour of seconds? It might look odd to see "80:00" when you really mean "1:20:00" for example.

double seconds=125;
TimeSpan.FromSeconds(seconds).ToString()
will give you : 00:02:05. As per my understanding this built-in solution is more extensible, since it can give you hours too, without any plumbing of the logic.

var seconds = 60;
//10,000 ticks in a millisecond
var ticks = seconds*10000*1000;
DateTime dt = new DateTime(ticks);
dt.ToString("mm:ss");

Simple maths. 60 seconds to a minute.
int mins = totalseconds/60;
int secs = totalseconds % 60;
Console.Writeline(string.Format("{0}:{1}", mins, secs));

Not strictly answering the original question, but in case anyone (or myself) in the future comes here from google wanting to format a float with milliseconds as well:
float secs = 23.69;
string m_ss_mmm = string.Format("{0}:{1:00}.{2:000}", (int)secs / 60, (int)(secs % 60), (secs - ((int)secs)) * 1000);
Result:
0:23.690

An alternative way to display the seconds as e.g. "2:05" could be to use PadLeft.
string time = minutes.ToString() + ":" + seconds.ToString().PadLeft(2,'0');

What works for me...
public static string SecondsToMinutes(int seconds)
{
var ts = new TimeSpan(0, 0, seconds);
return new DateTime(ts.Ticks).ToString(seconds >= 3600 ? "hh:mm:ss" : "mm:ss");
}

If you need it as float or double:
float seconds = 339;
float totalTimeInMins = (float) (Math.Floor(seconds / 60) + (seconds % 60) / 100);

Related

Adding Duration that contains frames

I have a duration that contains frames:
e.g1: 00:00:00:00
hh:mm:ss:FR
FR - stands for frames which is 25 frames for the middleast/asia region.
But in C# it takes the last FR as seconds (which is 60seconds).
e.g2: 00:00:00:00
DD:hh:mm:ss
Now how do I add e.g1 in C#
Can I know with this format how do I add two duration.
TimeSpan t1 = TimeSpan.Parse(duration);
TimeSpan t2 = TimeSpan.Parse("00:00:30:18");
TimeSpan t3 = t1.Add(t2);
in this duration "00:00:30:18" 18 is considered as milliseconds and not frames, so Timespan.Duration won't work for you, and you need something custom (for displaying might work but not adding and subtracting):
public static class Extensions
{
public static TimeSpan AddWithFrames(this TimeSpan x, TimeSpan ts)
{
int fr = ts.Seconds + x.Seconds;
TimeSpan result = x.Add(ts).Add(new TimeSpan(0,0,fr/25,0));
return new TimeSpan(result.Days, result.Hours, result.Minutes, fr % 25);
}
}
And use it like:
TimeSpan t1 = TimeSpan.Parse(duration);
TimeSpan t2 = TimeSpan.Parse("00:00:30:18");
TimeSpan t3 = t1.AddWithFrames(t2);
you can use a custom class that handles operations with SMPTE timecodes.
you do not need to reinvent the wheel, as this project handles all different kinds of framerates and frame drops:
https://github.com/ailen0ada/Timecode4net
using Timecode4net;
var start = Timecode.FromString(input: "00:00:05:15", frameRate: FrameRate.fps25, isDropFrame: false);
var end = Timecode.FromString("00:00:10:22", FrameRate.fps25, false);
Console.WriteLine((end.TotalFrames - start.TotalFrames)/25.0);
gives you 5,28
Here is how I did it unless someone has a better way to simplify this, kindly please share
string timecode1 = "00:05:00:04";
string timecode2 = "00:06:00:24";
int hours1 = Int32.Parse(timecode1.Substring(0,2))*90000;
int minutes1 = Int32.Parse(timecode1.Substring(3, 2))*1500;
int seconds1 = Int32.Parse(timecode1.Substring(6, 2))*25;
int frames1 = Int32.Parse(timecode1.Substring(9, 2));
int hours2 = Int32.Parse(timecode2.Substring(0, 2)) * 90000;
int minutes2 = Int32.Parse(timecode2.Substring(3, 2)) * 1500;
int seconds2 = Int32.Parse(timecode2.Substring(6, 2)) * 25;
int frames2 = Int32.Parse(timecode2.Substring(9, 2));
int time1 = hours1 + minutes1 + seconds1 + frames1;
int time2 = hours2 + minutes2 + seconds2 + frames2;
int totaltime = time1 + time2;
int hours = totaltime / 90000;
int minutes = ((totaltime % 90000)) / 1500;
int seconds = ((totaltime % 90000) % 1500 )/ 25;
int frames = ((totaltime % 90000) % 1500) % 25;

Convert seconds to hhh:mm:ss in a chart

I have a MsSql database which calculates the timespan between two dates in seconds. That works fine. I use this column afterwards in C# and write them in an array.
This array is the input for a chart later on.
So far this works well, but I cannot find a way to display the seconds in a format like hhh:mm:ss as the timespan can be greater than 24h.
I tried ChartArea.AxisY.LabelStyle.Format = "hhmmss"; but it does not work at all.
Does anybody has an idea how I could do that?
EDIT:
I add the data this way:
chart2.Series.Clear();
chart2.ChartAreas.Clear();
Series BoxPlotSeries = new Series();
ChartArea ChartArea2 = new ChartArea();
ChartArea ChartArea3 = new ChartArea();
chart2.ChartAreas.Add(ChartArea2);
chart2.ChartAreas.Add(ChartArea3);
ChartArea2.Name = "Data Chart Area";
ChartArea3.Name = "BoxPlotArea";
BoxPlotSeries.Name = "BoxPlotSeries";
BoxPlotSeries.ChartType = SeriesChartType.BoxPlot;
BoxPlotSeries.ChartArea = "BoxPlotArea";
chart2.Series.Add(BoxPlotSeries);
Series Input1 = new Series();
Input1.Name = "Input1";
Input1.ChartType = SeriesChartType.Point;
Input1.ChartArea = "Data Chart Area";
chart2.Series.Add(Input1);
chart2.Series["Input1"].Points.DataBindY(InputArray);
chart2.ChartAreas["BoxPlotArea"].AxisX.CustomLabels.Add(2, 0.0, "BoxPlot1");
chart2.Series["BoxPlotSeries"]["BoxPlotSeries"] = "Input1";
chart2.Series["BoxPlotSeries"]["BoxPlotShowMedian"] = "true";
chart2.Series["BoxPlotSeries"]["BoxPlotShowUnusualValues"] = "false";
chart2.Series["BoxPlotSeries"]["PointWidth"] = "0.5";
chart2.Series["BoxPlotSeries"].IsValueShownAsLabel = false;
ChartArea2.Visible = false;
ChartArea3.BackColor = Color.FromArgb(224,224,224);
//I tried to format it this way but it didn't work
//ChartArea3.AxisY.LabelStyle.Format = "{0:HHHmmss}";
chart2.ChartAreas["BoxPlotArea"].AxisX.LabelStyle.Angle = -90;
EDIT2:
And here's how I populate the input array
int[] InputArray = new int[1000000];
int c = 0;
con.Open();
dr = cmd.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
int n;
if (int.TryParse(dr[0].ToString(),out n) == true)
{
InputArray[c] = Convert.ToInt32(dr[0].ToString());
c++;
}
}
}
if (c == 0) { c = 1; }
Array.Resize(ref InputArray, c - 1);
EDIT 3:
The Boxplot should look like this in the end:
In Excel the format to display hours greater than 24 is called "[h]:mm:ss;#"
EDIT4:
Thanks to #TAW I nearly managed to solve my problem. I made some adjustments to his solution and came up with this:
In the chart code block:
The Value "max" is set before.
ChartArea3.AxisY.MajorTickMark.Interval = addCustomLabels(ChartArea3, BoxPlotSeries, 60 * 60, max);
int addCustomLabels(ChartArea ca, Series series, int interval, int max)
{
int tickNo = 0;
ca.AxisY.CustomLabels.Clear();
if(max / interval > 10)
{
interval = (max / 10) - (max / 10) % (60*30);
tickNo = (max / 10) - (max / 10) % (60*30);
}
if (max / interval <= 2 )
{
interval = (max / 4) - (max / 4) % (60 * 15);
tickNo = (max / 4) - (max / 4) % (60 * 15);
}
for (int i = 0; i < max; i += interval)
{
CustomLabel cl = new CustomLabel();
cl.FromPosition = i - interval / 2;
cl.ToPosition = i + interval / 2;
cl.Text = hhh_mm_ss(i);
ca.AxisY.CustomLabels.Add(cl);
}
return tickNo;
}
My problem is now, that sometimes no axis lable (apart from 0:00) is shown even when the code runs through it without any problems.
Has anybody and idea what could be wrong?
Your task involves two parts:
displaying seconds in the hhh:mm:ss format
putting them as labels on the y-axis
There is no suitable date-time formatting string for this in c#, so we can't make use of the built-in automatic labels and their formatting.
There also no way to use expressions that call a function on the automatic labels, unfortunately.
So we can't use those.
Instead we will have to add CustomLabels. This is not very hard but does take a few steps..
But let's start with a function that converts an int to the hhh:mm:ss string we want; this should do the job:
string hhh_mm_ss(int seconds)
{
int sec = seconds % 60;
int min = ((seconds - sec)/60) % 60;
int hhh = (seconds - sec - 60 * min) / 3600;
return hhh > 0 ? string.Format("{2}:{1:00}:{0:00}", sec, min, hhh)
: min + ":" + sec.ToString("00");
}
Maybe it can be optimized, but for our purpose it'll do.
Next we need to create the CustomLabels. They will replace the normal axis labels and we need to add them in a separate loop over the data after each binding.
One special thing about them is their positioning. Which is smack between two values we need to give them: the FromPosition and ToPosition, both in the unit of the axis-values.
Another difference to normal, automatic Labels is that it is up to us to create as many or few of them as we need..
This function tries to create a number that will go up to the maximum y-value and space the CustomLabels at a given interval:
void addCustomLabels(ChartArea ca, Series series, int interval)
{
// we get the maximum form the 1st y-value
int max = (int)series.Points.Select(x => x.YValues[0]).Max();
// we delete any CLs we have
ca.AxisY.CustomLabels.Clear();
// now we add new custom labels
for (int i = 0; i < max; i += interval)
{
CustomLabel cl = new CustomLabel();
cl.FromPosition = i - interval / 2;
cl.ToPosition = i + interval / 2;
cl.Text = hhh_mm_ss(i);
ca.AxisY.CustomLabels.Add(cl);
}
}
The first parameters to call this are obvious; the last one however is tricky:
You need to decide to interval you want your labels to have. It will depend on various details of your chart:
the range of values
the size of the chart area
the size of the font of the axis
I didn't set any special Font in the function; CustomLabels use the same Font as normal axis labels, i.e. AxisY.LabelStyle.Font.
For my screenshot I prepared the chart like this:
ca.AxisX.Minimum = 0;
ca.AxisY.MajorTickMark.Interval = 60 * 60; // one tick per hour
addCustomLabels(ca, s, 60 * 30); // one label every 30 minutes
I have also added DataPoint Labels for testing to show the values..:
series.Points[p].Label = hhh_mm_ss((int)y) + "\n" + y;
Here is the result:
UPDATE: This answer may be quite useful for other readers, but it pretty much misses the OP's issues. I'll leave it as it stands, but it will not help in creating specially formatted y-axis labels..
Most Chart problems stem from invalid or useless x-values. The following discussion tries to help avoiding or getting around them..
A number is a number and you can't simply display it as a DateTime, or for that matter a TimeSpan.
So you need to add the X-Values as either DateTime or as double that contain values that can be converted to DateTime. The fomer is what I prefer..
So instead of adding the seconds directly add them as offsets from a given DateTime:
Change something like this
series.Points.AddXY(sec, yValues);
To this:
var dt = new DateTime(0).AddSeconds(sec);
series.Points.AddXY(dt, yValues);
Now you can use the date and time formatting strings as needed..:
chartArea.AxisX.LabelStyle.Format = "{mm:ss}";
You could also add them as doubles that actually are calculated from DateTimes via the ToOADate:
series.Points.AddXY(dt.ToOADate(), yValues);
But now you will have to set the ChartValueType.DateTime and probably also AxisX.IntervalType and AxisX.Interval to make sure the chart gets the formatting right..:
s.XValueType = ChartValueType.DateTime;
ca.AxisX.Interval = 5;
ca.AxisX.IntervalType = DateTimeIntervalType.Seconds;
ca.AxisX.LabelStyle.Format = "{mm:ss}";
Pick values that suit your data!
Note that the problem with your original code is that the X-Values internally always are doubles, but the seconds are not integer values in them but fractional parts; so you need some kind of calculation. That's what ToOADate does. Here is a short test that shows what one second actually does amount to as a OADate double :
Best add the X-Values as DateTimes so all further processing can rely on the type..
Update I just saw that you have finally added the real code to your question and that is uses Points.DataBindY. This will not create meaningful X-Values, I'm afraid. Try to switch to Points.DataBindXY! Of course the X-Values you bind to also need to follow the rules I have explained above..!
You can do a loop over your array and convert the numbers like I shown above; here is a simple example:
int[] seconds = new int[5] { 1, 3, 88, 123, 3333 };
double[] oaSeconds = seconds.Select(x => new DateTime(0).AddSeconds(x).ToOADate())
.ToArray();
If you are trying to show more than 2 digits of hour I think this should work for you
//yourTimeSpan is the TimeSpan that you already have
var hoursDouble = Math.Floor(yourTimeSpan.TotalHours);
string hours;
string minutes;
string seconds;
//check hours
if(hoursDouble < 10)
{
hours = string.Format("0{0}", hoursDouble);
}
else
{
hours = hoursDouble.ToString();
}
//check minutes
if (yourTimeSpan.Minutes < 10)
{
minutes = string.Format("0{0}", yourTimeSpan.Minutes);
}
else
{
minutes = yourTimeSpan.Minutes.ToString();
}
//check seconds
if (yourTimeSpan.Seconds < 10)
{
seconds = string.Format("0{0}", yourTimeSpan.Seconds);
}
else
{
seconds = yourTimeSpan.Seconds.ToString();
}
string formattedSpan = String.Format("{0}:{1}:{2}", hours, minutes, seconds);
Update: I think this should solve the problem you were seeing with single digit numbers

How can i calculate the difference between a stored DateTime.Now and a current DateTime.Now?

I have a global var that i'm getting the DateTime.Now once i click a button:
dt = DateTime.Now;
Then inside a progresschanged event i'm doing:
var currentTime = DateTime.Now;
Now i need to calculate the difference between the currentTime and the stored time(dt) in seconds. Then i need to Divide BytesSent by the difference in seconds.
This is the progresschanged event i'm using:
double mbSent = 0;
int percentComplete = 0;
static string progress = "";
static string ttt = "";
private void videosInsertRequest_ProgressChanged(IUploadProgress obj)
{
stringProgressReport[1] = obj.Status.ToString();
backgroundWorker1.ReportProgress(0, 1);
mbSent = ((double)obj.BytesSent) / (1 << 20);
stringProgressReport[2] = mbSent.ToString();
backgroundWorker1.ReportProgress(0, 2);
percentComplete = (int)Math.Round(((double)obj.BytesSent) / totalBytes * 100);
stringProgressReport[3] = percentComplete.ToString();
backgroundWorker1.ReportProgress(0, 3);
var currentTime = DateTime.Now;
}
At the bottom of the event i need ot make the calculation and this way i can report the average speed. File upload speed.
EDIT
I'm getting exception when doing:
var currentTime = DateTime.Now;
TimeSpan diff = currentTime - dt;
int diffSeconds = (int)diff.TotalSeconds;
long averageSpeed = obj.BytesSent / diffSeconds;
both obj.BytesSent and diffSeconds are 0 so i get exception cant divide by zero on the averageSpeed.
Why diffSeconds is 0 ? Tried to calculate the time difference between dt and currentTime.
EDIT
This is what i did now:
if (obj.BytesSent != 0)
{
var currentTime = DateTime.Now;
TimeSpan diff = currentTime - dt;
var diffSeconds = (DateTime.Now - dt).TotalSeconds;
long averageSpeed = diffSeconds != 0 ? obj.BytesSent / diffSeconds : 0L;
double MBunits = ConvertBytesToMegabytes(averageSpeed);
stringProgressReport[4] = MBunits.ToString();
backgroundWorker1.ReportProgress(0, 4);
}
But getting error now on the long averageSpeed cant convert type double to long.
And this is the method that i use to convert to MegaBytes:
static double ConvertBytesToMegabytes(long bytes)
{
return (bytes / 1024f) / 1024f;
}
And in the backgroundworker progresschanged event:
label8.Text = stringProgressReport[4];
How can i show the user something nicer ? for example the speed something like:
The average speed is: 0.5 MB/s then 0.9 MB/s then 1.6 MB/s in this format or something else nicer.
You can simply substract two DateTime objects:
TimeSpan diff = currentTime - dt;
int diffSeconds = (int) diff.TotalSeconds;
var elapedSeconds = (DateTime.Now-dt).TotalSeconds;
You need a little bit of defensive programming to prevent the exception:
var diffSeconds = (DateTime.Now - dt).TotalSeconds;
long averageSpeed = diffSeconds !=0 ? obj.BytesSent / diffSeconds : 0L;

Remaining time based on progress?

I would like to output the time remaining for a process on the following format:
d hh:mm:ss
When the process start, it sets a DateTime startTimevariable with the current time.
From there I have timer on my GUI that updates a label every second and here is what I have to calculated the remaining time:
TimeSpan timeRemaining = TimeSpan.FromTicks(DateTime.Now.Subtract(startTime).Ticks * (iProgress.Maximum - iProgress.Value) / iProgress.Value);
And using on the label as:
labelTimeRemaining.Text = timeRemaining.ToString(#"d\ hh\:mm\:ss");
However the time variation is displayed is going on very oddly jumping several minutes with getting into a steady mode.
I know it should jump on the begin but it should stabilize at some point right ?
I process about 1~3 records per second however the time remaining is jumping 10~20 minutes every update.
What am I doing wrong or how could I fix this issue ?
Let me know if u need more info or code.
UPDATE
Below is portion of the code I am using:
private Stopwatch _timer = new Stopwatch();
private int _total = 0;
private int _current = 0;
Start a thread or task with:
private void MyTask()
{
_timer.Reset();
_timer.Start();
for (int i = 0; i < _total; i++)
{
_current++;
Thread.Sleep(500);
}
_timer.Stop();
}
Create a winforms Timer with the below function to run every second:
if (_timer.IsRunning && _current > 0)
{
float elapsedMin = ((float)_timer.ElapsedMilliseconds / 1000) / 60;
float minLeft = (elapsedMin / _current) * (_total - _current);
TimeSpan eta = TimeSpan.FromMinutes(minLeft);
iStatus.Text = eta.ToString(#"d\ hh\:mm\:ss");
}
Based on the comments you provided, when you are working with 10K to 10M records, that a fluctuation is rather big as you could see. Here is the test example that will show you the fluctuation.
DateTime dt = DateTime.Now;
Thread.Sleep(3000);
TimeSpan ts = TimeSpan.FromTicks(DateTime.Now.Subtract(dt).Ticks * (100000 - 7) / 7);
Debug.WriteLine(ts.ToString());
Thread.Sleep(1000);
ts = TimeSpan.FromTicks(DateTime.Now.Subtract(dt).Ticks * (100000 - 9) / 9);
Debug.WriteLine(ts.ToString());
Also, even if you take care of integer division
DateTime dt = DateTime.Now;
Thread.Sleep(3000);
TimeSpan ts = TimeSpan.FromTicks((long)((double)DateTime.Now.Subtract(dt).Ticks * (100000.0 - 7.0) / 7.0));
Debug.WriteLine(ts.ToString());
Thread.Sleep(1000);
ts = TimeSpan.FromTicks((long)((double)DateTime.Now.Subtract(dt).Ticks * (100000.0 - 9.0) / 9.0));
Debug.WriteLine(ts.ToString());
But if you could normalize your records number to percents. Let's say you have 100K records, 1K is one percent and that is done in approximately 1000/2/60 around 8 minutes. After 32 minutes you will have 4% done. After another you will have 6% done and after another 24 minutes you will have around 9% done but lets say 10%. After more 30 minutes you should have 14% done. And now, if you update your textBox rarely the users will have the illusion that you really know how long it will take, and you will end up changing time for hour or two, but do it on every minute or on every percent changed (have you ever copied 30GB on Windows?)
DateTime dt1 = DateTime.Now;
DateTime dt2 = DateTime.Now;
dt2 = dt2.AddMinutes(32);
ts = TimeSpan.FromTicks(dt2.Subtract(dt1).Ticks * (100 - 4) / 4);
Debug.WriteLine(ts.ToString());
dt2 = dt2.AddMinutes(16);
ts = TimeSpan.FromTicks(dt2.Subtract(dt1).Ticks * (100 - 6) / 6);
Debug.WriteLine(ts.ToString());
dt2 = dt2.AddMinutes(24);
ts = TimeSpan.FromTicks(dt2.Subtract(dt1).Ticks * (100 - 10) / 10);
Debug.WriteLine(ts.ToString());
dt2 = dt2.AddMinutes(30);
ts = TimeSpan.FromTicks(dt2.Subtract(dt1).Ticks * (100 - 14) / 14);
Debug.WriteLine(ts.ToString());

Faster alternative to DateTime.FromFileTime(fileTime).ToLocalTime().ToString()

While profiling my application I found that DateTime.FromFileTime(long fileTime) is slow.
Does anyone know of a fast managed equivalent or the windows file time format?
[EDIT]
I was able to get some speed gains doing the following:
var timeStr = FastTimeStringFormat(new DateTime(fileTime + 0x701ce1722770000L, DateTimeKind.Utc).ToLocalTime()); // + 0x701ce1722770000L is the offset needed to convert to UTC DateTime
For more speed but less safety (no intra-day daylight savings time checks), you can cache the ToLocalTime offset (long) and spare the more expensive expensive ToLocalTime() call.
On App Start:
long fileTimeOffset = DateTime.Today.Subtract(DateTime.Today.ToUniversalTime()).Ticks + 0x701ce1722770000L;
Then in your critical path:
var timeStr = FastTimeStringFormat(new DateTime(fileTime + fileTimeOffset));
As it turned out ToString is very expensive and the following is faster.
public static unsafe string FastTimeStringFormat(DateTime time)
{
// modified version from the following post:
// http://geekswithblogs.net/akraus1/archive/2006/04/23/76146.aspx
// this one is also more accurate because of true divide by 10, beware of less accurate versions that do not use division
char* FixedCharArray = stackalloc char[13];
int hour = time.Hour; // Cache property values
int minute = time.Minute;
int second = time.Second;
int ms = time.Millisecond;
// hour
FixedCharArray[0] = (Char)('0' + hour / 10);
FixedCharArray[1] = (Char)('0' + hour % 10);
FixedCharArray[2] = ':';
// minute
FixedCharArray[3] = (Char)('0' + minute / 10);
FixedCharArray[4] = (Char)('0' + minute % 10);
FixedCharArray[5] = ':';
// seconds
FixedCharArray[6] = (Char)('0' + second / 10);
FixedCharArray[7] = (Char)('0' + second % 10);
FixedCharArray[8] = '.';
// miliseconds
FixedCharArray[9] = (Char)('0' + ms / 100);
FixedCharArray[10] = (Char)('0' + ms % 100 / 10);
FixedCharArray[11] = (Char)('0' + ms % 10);
return new String(FixedCharArray);
}
DateTime.FromFileTime() is implemented in managed code, there are no P/Invoke calls involved.
The performance hit you're experiencing might come from the conversion to local time that is performed internally. Try using DateTime.FromFileTimeUtc() instead, if at all possible.

Categories

Resources