Using DateTime for a duration of time e.g. 45:00 - c#

I'd just like to know if it is possible to use the DateTime type for durations such as 45:00 (45 minutes) or 120:00 (120 minutes). These values also need to be stored into a Local Sql Server DB. If it is possible, could anyone possibly hint how this could be done using Datetime, or if not just let me know a way it could be done using a different type.
Thank you in advance,
Jamie

You should use the TimeSpan structure
TimeSpan interval = new TimeSpan(0, 45, 0);
Console.WriteLine(interval.ToString());
For the database storing part, you could store the property Ticks because a specific constructor for the TimeSpan structure allows to instantiate a new TimeSpan passing the Ticks value
long ticks = GetTimeSpanValueFromDb();
TimeSpan interval = new TimeSpan(ticks);
I wish to add also that you need a BIGINT T-SQL datatype field to store a long NET datatype

I store durations in seconds in the database and then convert to HH:MM:SS format when comes time to display the data.

Why don't you use TimeSpan instead? You can convert them to Ticks (int), store them in the db and the reverse the process when you need the value.

This is merely a matter of interpretation. SQL Server stores datetime as two four byte integers. One is a signed int count of days from a reference date, the other is an unsigned time of day such that 32bits exactly maps 24 hours. Without the implicit epoch, this isn't a datetime, it's a duration. Nothing prevents you from interpreting it that way.
Of course, it would be more convenient to pick a unit and simply use a float. This is what Windows does, storing datetime as a number of days from a reference date expressed as an 8-byte float (a double).
Personally I don't like "day" as a unit of time. The rotational period of our planet is not constant, and it is necessary to mess about with leap seconds to maintain the illusion that there are 86400 seconds in every day. A better choice is the SI unit, the second, which is defined in terms of repeatable, invariant physical constants.
Better again would be the picosecond, since we could dump the double and use an int64, with all the attendant arithmetical and comparative performance advantages. Depiction in mixed human scale units (yyyy mmm d HH:mm:ss) is already something of a trial. Mapping functions that currently work with fractional days could trivially be scaled to microseconds, although the compensation for leap seconds and leap days would have to be rewritten.
I say picosecond because this is the finest division that fits in 64 bits while encompassing a useful span of time (50,000 years). Femto fits, but fifty years isn't wide enough. I know that eventually there be a year 50K problem but frankly I doubt anyone but archeologists will care about records from 50,000 years ago.

Related

.NET datetime Millisecond precision issue when converting from string to datetime

Hi.
I am trying to convert an incoming datetime value that comes to our system in a string format. It seems that when the precision of milliseconds is higher than 7, the datetime parsing in .NET does not seem to like the value and cannot convert/parse the value. I am a bit stuck on what to do for this? My only current thought is there is a limit on the millisecond size and that anymore precision is not possible? But I want to confirm this is the case rather than assume.
Example:
string candidateDateTimeString = "2017-12-08T15:14:38.123456789Z";
if (!success)
{
success = DateTime.TryParseExact(trayportDateTimeString, "yyyy-
MM-dd'T'HH:mm:ss.fffffffff'Z'",
CultureInfo.InvariantCulture, dateTimeStyles, out dateTime);
}
If I reduce the 'f' values down to just 7, then date time parsing works fine. Is there a limit? Or am I doing something obvious wrong?
According to Custom Date and Time Format Strings docs, 7 is maximum supported digits of second fraction.
Internally, all DateTime values are represented as the number of ticks (the number of 100-nanosecond intervals) that have elapsed since 12:00:00 midnight, January 1, 0001.
https://msdn.microsoft.com/en-us/library/system.datetime(v=vs.110).aspx
see also: https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings
Precision of date and time values is more complex than you might think. There are different levels of precision involved:
Precision of DateTime
DateTime stores the number of ticks since 01.01.0001 00:00 as a 64 bit value. One tick is 100 nanoseconds. Since this is the maximum precision that can be stored, it makes no sense to format to a precision higher than that. You can just add as many zeros as you need to represent a higher precision. If you need to represent shorter timespans than 100 nanoseconds, you need to use a different type, such as an Int64 with a custom tick size.
Precision of DateTime.Now
When you call DateTime.Now, you get a much lower precision than DateTime can store. The exact value depends on the system clock, but it is usually in the milliseconds range.
Precision of Stopwatch
When you measure the time with Stopwatch, depending on your system, you might get the time from a high performance clock, which more precise than the clock used for DateTime.Now, but still less than 100 nanoseconds. On a system without high performance clock, the precision is the one of the regular system clock.
Summary
Unless the value that you are parsing originates from a high precision clock (like an atomic clock), parsing it to the full precision of DateTime, makes not much practical sense. And if it comes from such a source, you need to resort to a different data type to represent the value.

Which datatype to use to store TimeTaken field in SQLIte?

I want to create a field in SQLite DB(using C#) to store time taken(duration) field. The value will be in hr:min:sec format, like '10:10:00' which means 10 hrs, 10 min and 00 seconds. WHich Data type should I use for this? I know DateTime will not be adequate since its used to store date-time.
Use a TimeSpan in C#. This is meant to represent an elapsed duration of time, which is what you are describing.
In SQLite, you should store an INTEGER type so that your data is sortable. You simply need to decide what granularity you need.
For example, you could store the TimeSpan.Ticks if you care about the absolute finest precision possible. You would need an INTEGER of 8 bytes for this. When loading, you can use either TimeSpan.FromTicks, or the constructor new TimeSpan(ticks).
More likely, you will want to store a whole number of seconds, which you can get from TimeSpan.TotalSeconds. You could probably use an INTEGER of 4 bytes for this. When loading, you can use TimeSpan.FromSeconds to recreate the timespan from your integer.
DateTime or TimeSpan would be more than adequate, but SQLite doesn't support them.
In SQLite, possible data types are TEXT, INTEGER, REAL and BLOB (equivalent to .NET String, Int64, Double and Byte array respectively).
All you have to do is manipulate your C# DateTime or TimeSpan to your preferred SQLite data type.
I think that #Matt Johnson answer is the most adequate, however, I came out with another approach. In my case, the problem was a little bit different. I had to store reservations for a restaurant, and among others I had these 2 fields:
DateTime StartDateTime
TimeSpan Duration
Since you can't store TimeSpan in Sqlite I create a column name EndDateTime, of type DateTime. So Duration is the difference between EndDateTime and StartDateTime, like this:
StartDateTime = reader.GetDateTime(5);
Duration = reader.GetDateTime(6).Subtract(StartDateTime);

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?

Type to store time in C# and corresponding type in T-SQL

I would like to know how to store time in C# and T-SQL. I know that both of them provide a DateTime type but I just need to store a time. For instance:
var startTime = 9PM;
var endTime = 10PM;
And then store/retrieve this values from a database. Thanks in advance.
Francesco
C#
Whether to use a DateTime or TimeSpan type in C# to store 9 PM is up to taste. Personally, I'd use DateTime, leaving the date component empty, since that's semantically closer to what you want. (A TimeSpan is designed to hold time intervals, such as "21 hours".)
The documentation supports both options. This is from the documentation of TimeSpan:
The TimeSpan structure can also be used to represent the time of day, but only if the time is unrelated to a particular date.
On the other hand, the MSDN article Choosing Between DateTime, DateTimeOffset, and TimeZoneInfo mentions the following:
The DateTime structure is suitable for applications that do the following:
* Work with dates only.
* Work with times only.
[...]
T-SQL
SQL Server has a time data type.
In C# there is not a type to hold only a time. There is TimeSpan, but it's intended to keep a period of time and not really a component of a DateTime (i.e. hours and minutes) only.
Starting with SQL Server 2008 there is a time type (Using Date and Time Data) that does only store a time component.
EDIT: Misread your question at first. TimeSpan is exactly what you're looking for and it can be stored in a time type with SQL 2K8.
In C# you'd probably want to use a TimeSpan structure if you just wanted to store a time interval. However, you seem to want to appear to store a start-time and an end-time, which would require storing two values. You could, therefore, use two TimeSpans (based on, say, number of minutes from midnight to represent the time) or you could just use two DateTime values and throw away the date component.
As has been noted, SQL Server 2008 has a Time datatype, but this isn't available in earlier versions which only have DateTime. You could also just store an Int representing number of minutes past midnight which can be easily converted to a TimeSpan (TimeSpan interval = TimeSpan.FromMinutes(60)).
Timespan in c# is how you manipulate time intervals. Contrary to what other posters are saying i don't think the Time data type is correct for storing time intervals in SQL, unless you actually want to store the start time and end time and not the time interval (i.e. 1 hour in you example). It is for storing a time of day, a bit like a DateTime but with no date. When i want to store a time interval in SQL I just use an int and then have it represent a unit of time appropriate to what I am trying to do (e.g.minutes, seconds, milliseconds etc. )

Handling and storing elapsed time

I'm having problems deciding on what is the best way is to handle and store time measurements.
I have an app that has a textbox that allows the users to input time in either hh:mm:ss or mm:ss format.
So I was planning on parsing this string, tokenizing it on the colons and creating TimeSpan (or using TimeSpan.Parse() and just adding a "00:" to the mm:ss case) for my business logic. Ok?
How do I store this as in a database though? What would the field type be? DateTime seems wrong. I don't want a time of 00:54:12 to be stored as 1901-01-01 00:54:12 that seems a bit poor?
TimeSpan has an Int64 Ticks property that you can store instead, and a constructor that takes a Ticks value.
I think the simplest is to just convert user input into a integer number of seconds. So 54:12 == 3252 seconds, so store the 3252 in your database or wherever. Then when you need to display it to the user, you can convert it back again.
For periods less than a day, just use seconds as other have said.
For longer periods, it depends on your db engine. If SQL Server, prior to version 2008 you want a datetime. It's okay- you can just ignore the default 1/1/1900 date they'll all have. If you are fortunate enough to have sql server 2008, then there are separate Date and Time datatypes you can use. The advantage with using a real datetime/time type is the use of the DateDiff function for comparing durations.
Most databases have some sort of time interval type. The answer depends on which database you're talking about. For Oracle, it's just a floating point NUMBER that represents the number of days (including fractional days). You can add/subtract that to/from any DATE type and you get the right answer.
As an integer count of seconds (or Milliseconds as appropriate)
Are you collecting both the start time and stop time? If so, you could use the "timestamp" data type, if your DBMS supports that. If not, just as a date/time type. Now, you've said you don't want the date part to be stored - but consider the case where the time period spans midnight - you start at 23:55:01 and end at 00:05:14, for example - unless you also have the date in there. There are standard build in functions to return the elapsed time (in seconds) between two date-time values.
Go with integers for seconds or minutes. Seconds is probably better. you'll never kick yourself for choosing something with too much precision. Also, for your UI, consider using multiple text inputs you don't have to worry about the user actually typing in the ":" properly. It's also much easier to add other constraints such as the minute and second values conting containing 0-59.
and int type should do it, storing it as seconds and parsing it back and forth
http://msdn.microsoft.com/en-us/library/ms187745.aspx

Categories