Why is Convert.ToDateTime() not working in this example? - c#

I'm trying to use both System.DateTime.Now.ToString() and Convert.ToDateTime and was running into some strange behavior. I have narrowed down the problem to the Convert.ToDateTime. For some reason a DateTime type set with System.DateTime.Now is not the same as one that has been converted from a string. However when you output either of them they appear to be the same.
(I have tried using Trim(), TrimStart(), and TrimEnd() to no avail.)
This is the output in console after running this in unity:
http://imgur.com/1ZIdPH4
using UnityEngine;
using System;
public class DateTimeTest : MonoBehaviour {
void Start () {
//Save current time as a DateTime type
DateTime saveTime = System.DateTime.Now;
//Save above DateTime as a string
string store = saveTime.ToString();
//Convert it back to a DateTime type
DateTime convertedTime = Convert.ToDateTime(store);
//Output both DateTimes
Debug.Log(saveTime + "\n" + convertedTime);
//Output whether or not they match.
if (saveTime == convertedTime)
Debug.Log("Match: Yes");
else
Debug.Log("Match: No");
//Output both DateTimes converted to binary.
Debug.Log(saveTime.ToBinary() + "\n" + (convertedTime.ToBinary()));
}
}

You lose a lot when you convert a DateTime to a string via DateTime.ToString().
Even if you include the milliseconds like this:
DateTime convertedTime =
new DateTime(
saveTime.Year,
saveTime.Month,
saveTime.Day,
saveTime.Hour,
saveTime.Minute,
saveTime.Second,
saveTime.Millisecond);
you would still get a different DateTime that is not equal to the original one.
The reason for this is that internally a DateTime stores a number of ticks (since 12:00:00 midnight, January 1, 0001). Each tick represents one ten-millionth of a second. You need to get the same number of Ticks for the two DateTime objects to be equal.
So, to get an equal DateTime, you need to do this:
DateTime convertedTime = new DateTime(saveTime.Ticks);
Or if you want to convert it to a string (to store it), you can store the ticks as a string like this:
string store = saveTime.Ticks.ToString();
DateTime convertedTime = new DateTime(Convert.ToInt64(store));

The result of DateTime.ToString() does not include milliseconds. When you convert it back to DateTime, you basically truncate the milliseconds, so it returns a different value.
For example
var dateWithMilliseconds = new DateTime(2016, 1, 4, 1, 0, 0, 100);
int beforeConversion = dateWithMilliseconds.Millisecond; // 100
var dateAsString = dateWithMilliseconds.ToString(); // 04-01-16 1:00:00 AM (or similar, depends on culture)
var dateFromString = Convert.ToDateTime(dateAsString);
int afterConversion = dateFromString.Millisecond; // 0

I think you are losing your time zone during the ToString() method. So the re-converted DateTime ends up in a different time zone.
Check also the DateTime.Kind property.

Related

Get Time Value of DateTime string in DataGridView?

I am a beginner at C#. I have a DataGridView which displays:
string Column4 = DateTime.Today.AddDays(1).AddHours(7).ToString();
How do I then retrieve just the time value (i.e 07:00:00) as a string later?
EDIT: The date should be in the format it is currently and remain that way in DataGridView, but for example when I do:
string newString = Column4;
Console.WriteLine(newString);
How do I just pull the time value from Column4 rather than the whole date?
EDIT2: Saw the possible duplicate question and tried:
DateTime newString = DateTime.Parse(Column4);
newString.ToString("HH:mm");
Console.WriteLine(newString);
But this still produced:
02/05/2018 07:00:00
If you only need time value, you can use TimeSpan structure. This structure represents a time interval that you can adjust as you please. You can use the structure constructor and its method ToString() to store the string representation of that time.
This is the code you can use:
string Column4 = (new TimeSpan(7, 0, 0)).ToString();
If you need to use later the same TimeSpan value, I suggest you to store it in a variable:
TimeSpan time = new TimeSpan(7, 0, 0);
string Column4 = time.ToString();
Remember, if you want to make reference of a date, you can use DateTime structure. Else, if you need only the time, you can use TimeSpan structure.
To convert a TimeSpan structure to a Datetime structure you can do this:
DateTime date = DateTime.Today + new TimeSpan(7, 0, 0)).ToString();
Update: If you just need the time from a DateTime structure variable, you can format it:
string newString = DateTime.Parse(Column4).ToString("t");
// Result: 7:00
Or
string newString = DateTime.Parse(Column4).ToString("T");
// Result: 7:00:00
You can see more string formats at this Microsoft MSDN page.
In this Microsoft MSDN page is an example about how to instantiate a TimeSpan structure with desired time:
By calling one of its explicit constructors. The following example initializes a TimeSpan value to a specified number of hours, minutes, and seconds:
TimeSpan interval = newTimeSpan(2, 14, 18);
Console.WriteLine(interval.ToString()); // Displays "02:14:18".

How to convert the "time" from DateTime into int?

I have a DataGrid which contains a few values that are in hours and I wanted to know:
How to get ONLY the time from my DataGrid and convert it into an int (or double) variable.
My goal is to do a few operations with my DataGrid time values, like to add numbers into it
EXAMPLE:
Using my "dataGridView1.Rows[1].Cells[2].Value.ToString();" It'll show a DateTime value (which is inside my DataGrid), with this value, I wanna filter ONLY the time from this and convert it into an int
the part of my code which I wanna "capture" the time:
txtAtiv.Text = dataGridView1.Rows[0].Cells[1].Value.ToString();
string value = dataGridView1.Rows[0].Cells[2].Value.ToString();
lblLeft.Text = value.Split(' ')[1];
I wanna get the "value" (which is a DateTime value from the DataGrid) and convert it into an int.
note:
- The date for me in my dataGrid it's not relevant, I only have to pick the time (and yes, I know that I can't "split" DateTime to do them separately)
If you are willing to be limited to millisecond resolution, then this is fairly easy.
Given a date/time that you want to get the time part from as an int, you can get the number of milliseconds since midnight, like so:
DateTime dateTime = DateTime.Now;
int timeMsSinceMidnight = (int)dateTime.TimeOfDay.TotalMilliseconds;
If you want to reconstitute the original date and time from this, you need the original date and the time since midnight in milliseconds:
DateTime date = dateTime.Date; // Midnight.
DateTime restoredTime = date.AddMilliseconds(timeMsSinceMidnight);
Test program:
DateTime dateTime = DateTime.Now;
Console.WriteLine("Original date/time: " + dateTime );
int timeMsSinceMidnight = (int)dateTime.TimeOfDay.TotalMilliseconds;
DateTime date = dateTime.Date; // Midnight.
DateTime restoredTime = date.AddMilliseconds(timeMsSinceMidnight);
Console.WriteLine("Restored date/time: " + restoredTime);
The value returned from time.TimeOfDay is of type TimeSpan, which is convenient for storing time-of-day values.
If you want to turn your "milliseconds since midnight" back into a TimeSpan, you just do this:
var timeSpan = TimeSpan.FromMilliseconds(timeMsSinceMidnight);
First step is to convert string to DateTime. Use DateTime.TryParse(string value, out DateTime dt). Then as Mathew Watson rightly suggested, get the value of variable dt converted to milliseconds using dt.TimeOfDay.TotalMilliseconds. It is also possible to convert the span in TotalSeconds or TotalMinutes if it suits your requirement.
Try to avoid calling ToString() method directly before checking if cell value is null. If I want to avoid the check, I would make compiler to do it by using something like : Rows[3].Cells[2].Value + "" instead of Value.ToString().
Mixing Mathew's and Mukesh Adhvaryu's answers, I got into this one, and it fits perfectly on what I need, thank you guys for your support!
txtAtiv.Text = dataGridView1.Rows[0].Cells[1].Value + "";
string value = dataGridView1.Rows[0].Cells[2].Value + "";
lblLeft.Text = value.Split(' ')[1];
textStatus.Text = "";
DateTime timeConvert;
DateTime.TryParse(value, out timeConvert);
double time;
time = timeConvert.TimeOfDay.TotalMilliseconds;
var timeSpan = TimeSpan.FromMilliseconds(time);
lblSoma.Text = timeSpan.ToString();
static void Main(string[] args)
{
string time1 = "11:15 AM";
string time2 = "11:15 PM";
var t1 = ConvertTimeToInt(time1);
var t2 = ConvertTimeToInt(time2);
Console.WriteLine("{0}", t1);
Console.WriteLine("{0}", t2);
Console.WriteLine("{0:dd/MM/yyyy hh:mm tt}", ConvertIntToTime(t1));
Console.WriteLine("{0:dd/MM/yyyy hh:mm tt}", ConvertIntToTime(t2));
Console.ReadLine();
}
static long ConvertTimeToInt(string input)
{
var date = DateTime.ParseExact(input, "hh:mm tt", CultureInfo.InvariantCulture);
TimeSpan span = date.TimeOfDay;
Console.WriteLine("{0:dd/MM/yyyy hh:mm tt}", date);
return span.Ticks;
}
static DateTime ConvertIntToTime(long input)
{
TimeSpan span = TimeSpan.FromTicks(input);
var date = new DateTime(span.Ticks);
Console.WriteLine("{0:dd/MM/yyyy hh:mm tt}", date);
return date;
}

c# reproduce datetime from ticks

I have a datetime field like
{01/01/0001 00:01:02}
Millisecond = 30 and the Ticks for the above datetime field is
6203000000
The ticks save in the database as an int value which is 62030. I need to reproduce the above date time using the value in the database (62030). So I tried the following.
var data = 62030;
winTime = new DateTime().AddTicks(Convert.ToInt64(data.ToString().PadRight(10, '0')));
var b = winTime.Ticks;
var b = 6203000000. But it returns minute as 10 instead 01, second as 20 instead of 02 and Millisecond as 300 instead of 030.
Can anyone see what I'm doing wrong?
It seems to me that your "ticks 62030" is actually "milliseconds 62030" in which case it's very simple - you just need to multiply by "the number of ticks per millisecond" which is 10,000. You don't need to use DateTime for this at all:
// Note that if you want any significant length of time, you'd expect to get
// the data as a long, not an int
int data = 62030; // Milliseconds
long ticks = data * 10000L;
... and you certainly don't need string conversions. Converting to a string, padding, and then converting back again is a very tortuous and error-prone way of performing multiplication.
Or if you do need a DateTime:
int data = 62030; // Milliseconds
long dateTime = new DateTime(data * 10000L);
I strongly suspect that any DateTime value that early should actually be treated as a TimeSpan though - what's this really meant to represent? If so, it's even easier:
TimeSpan ts = TimeSpan.FromMilliseconds(data);
Date and time concepts are very easy to mix up, and you end up with some very subtle bugs. Personally I'd recommend using my Noda Time project which separates them more than .NET does, but even if you don't use the library it's worth looking at the list of concepts so you can think about them appropriately within .NET too.
Why not just use the DateTime constructor that accepts an Int64 representing ticks, such that:
var dateTimeFromTicks = new DateTime(ticks);
static void Main(string[] args)
{
/* read datetime now */
DateTime dt = new DateTime();
dt = DateTime.Now;
/* datetime convert to tick */
long TickeringTick = dt.Ticks;
Console.WriteLine("Date time now -> " + dt.ToString("yyyy.MM.dd HH:mm:ss.fffffff"));
Console.WriteLine("Converted to Ticks = " + TickeringTick.ToString());
/* convert tick to datetime */
long myTicks = TickeringTick;
DateTime dt2 = new DateTime(myTicks);
Console.WriteLine("Date from ticks :" + dt.ToString("yyyy.MM.dd HH:mm:ss.fffffff"));
Console.ReadLine();
}

Convert formatted date string to DateTime(int,int,int,int,int,int) to pass into a function

I am comparing the time now to a time stored somewhere in a database. The time stored in the database is in the format of "yyyyMMddHHmmss". For example, the database may return 201106203354 for a stored time value. I am then using a function to compare the time now to the time read in from the database.
What I am doing now:
Create 6 int variables
Take the sub-string from the formatted date string and convert the sub-string to an int32.
Pass the 6 int variables to the function.
What I would like to do:
Rather than splitting up the formatted date-time string, and seperately creating and assigning six variables to pass to the function, I would like to know if there is some way to simply convert the formatted date-time string into DateTime.
Please see my code as it will help to explain what I clearly cannot ...
Pass time now along with time read from database:
Private void passTime()
{
string timeStamp;
int year, month, day, hour, minutes, seconds;
DateTime dt = DateTime.Now;
timeStamp = dt.ToString("yyyyMMddHHmmss");
year = Convert.ToInt32(timeStamp.Substring(0, 4));
month = Convert.ToInt32(timeStamp.Substring(4, 2));
day = Convert.ToInt32(timeStamp.Substring(6, 2));
hour = Convert.ToInt32(timeStamp.Substring(8, 2));
minutes = Convert.ToInt32(timeStamp.Substring(10, 2));
seconds = Convert.ToInt32(timeStamp.Substring(12, 2));
MessageBox.Show(GetDifferenceDate(
new DateTime(year,month,day,hour,minutes,seconds),
// Example time from database
new DateTime(2011, 08, 11, 11, 40, 26)));
}
static string GetDifferenceDate(DateTime date1, DateTime date2)
{
if (DateTime.Compare(date1, date2) >= 0)
{
TimeSpan ts = date1.Subtract(date2);
return string.Format("{0} days",
ts.Days);
}
else
return "Not valid";
}
So, quite simply, I would like to compare two dates that are both in the format of "yyyyMMddHHmmss", or if this is not possible, I would like to convert the previous Date string into a DateTime.
I'm sure I left something out here, I will go back and read it again but please feel free to ask me anything that I left unclear.
Thank you,
Evan
You're looking for ParseExact:
DateTime.ParseExact(timeStamp, "yyyyMMddHHmmss", CultureInfo.InvariantCulture)

Add or Sum of hours like 13:30+00:00:20=13:30:20 but how?

I want to add seconds (00:00:02) or minutes (00:00:20) on datetime value (may be stored string type) but how? Examples:
13:30+02:02:02= 15:32:02 ,
13:30+00:00:01= 13:30:01 ,
13:30+00:01:00=13:31:00 or 13:30 (not important)
Can you help me? I need your cool algorithm :) Thanks again...
myDateTimeVariable.Add(new TimeSpan(2,2,2));
If you choose to use the TimeSpan, be aware about the Days part:
TimeSpan t1 = TimeSpan.Parse("23:30");
TimeSpan t2 = TimeSpan.Parse("00:40:00");
TimeSpan t3 = t1.Add(t2);
Console.WriteLine(t3); // 1.00:10:00
With DateTime:
DateTime d1 = DateTime.Parse("23:30");
DateTime d2 = DateTime.Parse("00:40:00");
DateTime d3 = d1.Add(d2.TimeOfDay);
Console.WriteLine(d3.TimeOfDay); // 00:10:00
Adding two datetimes from strings:
var result = DateTime.Parse(firstDate) + DateTime.Parse(secondDate);
Adding a string time to a datetime:
var result = existingDateTime.Add(TimeSpan.Parse(stringTime);
Adding time as in your example:
var result = TimeSpan.Parse("12:30:22") + TimeSpan.Parse("11:20:22");
Finally, your example as dates (not tested!):
var result = DateTime.Parse("12:30:22") + DateTime.Parse("11:20:22");
Note that this is sloppy coding, but you get the idea. You need to verify somehow that the string is actually parseable.
Not really sure what you're after, but can you not just use the built in functions to C#'s DateTime object?
DateTime myDate = DateTime.Now;
myDate = myDate.AddHours(1);
myDate = myDate.AddMinutes(30);
myDate = myDate.AddSeconds(45);
The problem is more abstract. As already mentioned, in .NET there are two types - DateTime and TimeSpan. The DateTime type represents a specific point in time. It's not an interval of time. It's a specific location in all time since the birth of the Universe. Even if you set the year/month/day components to 0, it will still represent some absolute point in time. Not a length of time.
The TimeSpan on the other hand represents some interval. 1 minute, 2 days, whatever. It's not specified WHEN, just HOW LONG.
So if you were to subtract two DateTime objects you would get a TimeSpan object that specifies how much time there is between them. And if you add a TimeSpan to a DateTime you get another DateTime. But you can't add a DateTime to another DateTime - that would make no sense.
It sounds to me like you should be working with TimeSpans all the time, because you are dealing with lengths of time, not absolute points in time. If you get these lengths from your source as a DateTime then that's actually not correct, and you should convert them to TimeSpans somehow. The parsing method is one way that has been suggested, but you might also try to subtract zero DateTime from it. That might be faster and more culture-independant.
use the TimeSpan structure. you can add TimeSpans together, or you can add a TimeSpan to a DateTime to produce a new DateTime.
You should have a look at TimeSpan.Parse. This converts a string to a TimeSpan object. That way you can do stuff like
TimeSpan a = TimeSpan.Parse(timeStringA)+TimeSpan.Parse(TimeStringB);
To split a string like "00:00:20+00:01:00" look at string.split
stringA = timeSting.split('+')[0];
stringb = timeSting.split('+')[1];
return string.Format("{0}:{1}:{2}", mytimespan.Hours
+ (mytimespan.Days*24),mytimespan.Minutes,mytimespan.Seconds);
static void Main(string[] args)
{
String timeText = "3/23/2015 12:00:13 AM";
String timeText2 = "3/23/2015 1:45:03 AM";
DateTime time = Convert.ToDateTime(timeText);
string temp = time.ToString("HH:mm:ss");
DateTime time2 = Convert.ToDateTime(timeText2);
string temp2 = time2.ToString("HH:mm:ss");
TimeSpan t1 = TimeSpan.Parse(temp);
TimeSpan t2 = TimeSpan.Parse(temp2);
Console.Out.WriteLine(t1 + t2); // 01:45:16
Console.ReadLine();
}

Categories