I am trying to build a nice, small database to run on a mobile application (Windows Mobile 5, if you are curious).
In the SQLite Documentation, the Date and Time Datatype is defined as follows:
1.2 Date and Time Datatype
SQLite does not have a storage class set aside for storing dates
and/or times. Instead, the built-in Date And Time Functions of SQLite
are capable of storing dates and times as TEXT, REAL, or INTEGER
values:
TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS").
REAL as Julian day numbers, the number of days since noon in Greenwich on November 24, 4714 B.C. according to the proleptic
Gregorian calendar.
INTEGER as Unix Time, the number of seconds since 1970-01-01 00:00:00 UTC.
Applications can chose to store dates and times in any of these
formats and freely convert between formats using the built-in date and
time functions.
So, saving my DateTime value as either a REAL (float) or INTEGER is the same size.
What about the TEXT format? There are 23 characters above in the text YYYY-MM-DD HH:MM:SS.SSS. Is that 8-bytes per character? If so, that is a HUGE waste of space to store in Text format (which is what I am currently doing).
What about the REAL format? Would I define a base date of November 24, 4714 B.C.? (I am not even sure if Visual Studio 2008 will let me do that. I've never tried.) Then get the TimeSpan between base date and date I want, extract the number of days, and store that?
// is this how to declare this date?
private static readonly DateTime nov24_4714bc = new DateTime(-4714, 11, 24);
public static double GetRealDate(DateTime dateTime) {
// FYI: subtracting dates in .NET returns a time span object
return (dateTime - nov24_4714bc).TotalDays;
}
What about the INTEGER format? Would I define a base date of 1970-01-01 00:00:00 UTC (please tell me how to do that!), then get the TimeSpan between base date and my input date, extract the number of seconds, and store that?
// is this a UTC date?
private static readonly DateTime utc1970_01_01 = new DateTime(1970, 1, 1);
public static double GetIntDate(DateTime dateTime) {
// FYI: subtracting dates in .NET returns a time span object
return (dateTime - nov24_4714bc).TotalSeconds;
}
Any help with this? I am a little confused on a few points.
Use the TEXT format if "human-readability" is important.
Use one of the numeric formats if saving space is important.
If you don't need millisecond precision, you can save space in the TEXT format by only including the part you do need. There are 3 shorter formats accepted by SQLite date/time functions:
YYYY-MM-DD HH:MM:SS (19 characters)
YYYY-MM-DD HH:MM (16 characters)
YYYY-MM-DD (10 characters)
(NEVER use MM/DD/YYYY; it's not supported, and it doesn't sort correctly.)
Would I define a base date of November 24, 4714 B.C.? (I am not even
sure if Visual Studio 2008 will let me do that. I've never tried.)
You can't: System.DateTime only supports the years 1 to 9999. You need to pick a different base date, and then do (dateTime - baseDate).TotalDays + baseDateJD, where baseDateJD is the Julian date of the base date. Some reasonable choices are:
0001-01-01 = JD 1721425.5
1970-01-01 = JD 2440587.5
2000-01-01 = JD 2451544.5
Related
I am exporting date values("24/11/2016") from excel file to SQL database table in C#.NET. I am using the following code into my function to parse the date values from string to Datetime. But it is not working. I tried to debug it but when it comes on that line, it's terminating. Anybody know what is the problem.
var date = row["Date"].ToString();
DateTime dates;
string format = "MM-dd-yyyy";
if (!DateTime.TryParseExact(date, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out dates))
{
continue;
}
else
{
dates = DateTime.Parse(date); //terminating at this line
}
Your format should be dd-MM-yyyy as you have 24/11/2016 as date, you can learn more about string formats in this MSDN article Custom Date and Time Format Strings
Change
string format = "MM-dd-yyyy";
To
string format = "dd-MM-yyyy";
Edit based on comments by OP - Storing formatted date in SQL server
The DateTime is stored in a SQL server in standard format that is not in fact the presentation format we see like "dd-MM-yyy". This article Solving the Datetime Mystery explains the internal SQL server format.
Excerpt from Solving the Datetime Mystery
So how does SQL Server internally store the dates? It uses 8 bytes to
store a datetime value—the first 4 for the date and the second 4 for
the time. SQL Server can interpret both sets of 4 bytes as integers.
For the date portion, the value SQL Server stores is the number of
days before or after a base date of January 1, 1900. Because of this
storage protocol, SQL Server assumed the date of January 1, 1900, when
I didn't supply the date in my first example. SQL Server internally
stored a value of 0. A negative number represents a date earlier than
January 1, 1900.
SQL Server stores the second integer for the time as the number of
clock ticks after midnight. A second contains 300 ticks, so a tick
equals 3.3 milliseconds (ms). You can see the values for days and
clock ticks by converting a datetime value to a binary(8) value and
using the substring function to extract each set of 4 bytes. The code
in Figure 3 then converts each set of 4 bytes into an integer.
Finally i did it using the following code:
string format = "dd/MM/yy";
if (!DateTime.TryParseExact(date, format, CultureInfo.InvariantCulture, DateTimeStyles.None,out dates))
{ continue; }
else
{ dates = DateTime.ParseExact(date, format, CultureInfo.InvariantCulture); }
String datetime = dates.ToString("yyyy-MM-dd");
Thanks to all.
How to remove a time in date time ? on column date its only display format
I store the value on repository combobox dropdown, and it store the value including the time. How do I remove the time?
I know there's so many question about this. But the solution was by converting it into a date.tostring("dd MMM yyyy"). Is there a solution beside convert it into string? I want the value was date time not a conversion of string.
The code I am using still giving me a time.
DateTime date = Convert.ToDateTime(gridView1.GetDataRow(i)["date"]);
You just forgot to specify the date at the end of the conversion
DateTime date = Convert.ToDateTime(gridView1.GetDataRow(i)["date"]).Date;
DateTime as the name implify, stores date and time.
You cannot remove time part from date because time is an integral part of date.
To understand this you will have to understand how the date and time are stored. Internally, the date and time is stored as a rational number (in fractions). In computer system 24 hours are considered as numeric 1, so when your value is increased by 1 that means your date is increased by 1 day. If the value is increased by 0.5 that means your date is increased by 12 hours (half day).
So, when you have value 42613.00 that means 31st August at midnight (just when the day started) and if you have value 42613.25 that means 6 AM of 31 Aug 2016 and 42613.50 means 12 noon of 31 Aug 2016 (and 42613.39236 means 9:25:00 AM of 31 Aug 2016)
The smallest fraction of time that need to be stored is 1 millisecond. That means the values of DateTime field should have a precision of more than 0.0000000115740740740741. But this is an irrational value (in binary) and hence cannot be stored as such (the nearest match is 1.00000000000000000000000000110001101101011101010000111010111111..., ... means there are more), so I can say that milliseconds are to their nearest approximation values.
.
That said,
if you wish to take only Date part, you can create your own class or struct to store date part of the DateTime and then override operators for date arithematic and provide implicit conversions to convert them to DateTime if any code that expect DateTime field.
I get some data from a PICK/UniVerse database that includes dates in a 4 or 5 character numeric format. Here are some examples .. I grabbed the date values from the database, and compared it to the date being shown in an application:
9832 12/1/1994
10027 6/14/1995
10594 1/1/1997
Is it possible to convert these into something that can be put into Access as a Date/Time value?
As A test, I put 9832 in Excel as a General format and then change it to Short Date, it comes up as 12/1/1926. So it's off by exactly 68 years. This was true for 10027 and 10594 as well.
In C# you can use DateTime.FromOADate
DateTime dt = DateTime.FromOADate(41481);
Returns a DateTime equivalent to the specified OLE Automation Date.
That will give you:
dt = {26/07/2013 12:00:00 AM}
Later on you can insert that Date in your Access database.
Access Date/Time values are actually double precision floats. The whole number portion represents the day and the integer portion represents the time of day.
It looks like those Pick date numbers correspond directly to the date portions of Access Date/Time values. So you can use CDate to transform them.
? CDate(41481)
7/26/2013
Experiment some more to get a feel for this:
? Date()
7/26/2013
? CDbl(Date())
41481
Note, although your question is tagged with c#, you don't need that to do these conversions. You can do them with an Access query and ask the db engine to apply those functions.
Since it turned out those date numbers are consistently offset by 68 years, you can still do the conversion in an Access query.
? DateAdd("yyyy", 68, CDate(9832))
12/1/1994
? DateAdd("yyyy", 68, CDate(10027))
6/14/1995
? DateAdd("yyyy", 68, CDate(10594))
1/1/1997
Or ...
? CDate(9832 + CLng(24837))
12/1/1994
? CDate(10027 + CLng(24837))
6/14/1995
? CDate(10594 + CLng(24837))
1/1/1997
A little late to this thread but I'll post some more detail: The Pick / MultiValue DBMS stores dates as an integer with date 0 = 12/31/1967. So as I write this on Jan 16, 2014 the internal Pick date is 16818. If you use the following you'll get that magic number 24837:
DateTime.Parse("12/31/1967").Subtract( DateTime.FromOADate(0)).Days
So add that to your Pick Date to get the OADate.
If you're using any of the common MV DBMS libraries for extracting data (UniObjects, U2.NET, mv.NET ...) you shouldn't need to convert the date like this. A typical function might look like:
string date = OConv( record["PurchaseDate"], "d2/" ); // "01/16/14"
Or rather than extracting the data in the internal DBMS format, you really should be getting it in external format to start. Ask the DBMS developer who provided the data to do this for you. It's real easy on their side to return " date'd2/' " rather than just "date".
Feel free to contact me directly if you need more info in this area.
All multivalue database dates (this includes UniVerse and UniData) are based on a base date of 31st December 1967. You can resolve this to an external data in a number of ways.
The favourite - e.g. if using SQL or one of the internal database tools is to create a data dictionary entry for the field concerned with a date conversion field, For example:
'D2' for a 2-digit year
'D4' for a 4-digit year
'D4/' for a 4-digit year with slash separators
'D4/E' for a 4-digit year with slash separators and explicitly in European format (DD/MM/YYYY) as compared to US format (MM/DD/YYYY).
If no explicit formatting is given then the format will default to environmental settings. There are other formatting options as well and many can be used in combination (as with the above).
As previously advised, the alternative is to adjust the raw date with a formula. The date is in days since 31st December 1967 - The base data for all multivalue databases.
I have the value 40880.051388 and am storing it as a double, if I open Excel and paste in a cell and apply the following custom format "m/d/yyyy h:mm" to that cell, I get "12/3/2011 1:14"
How can I do this parsing/Conversion in C#? I don't know if the value is milliseconds from a certain checkpoint, like epoch time, or if the value is in some specific prepared format, but how does excel come up with this particular value? Can it be done in C#?
I've tried working with TimeSpan, DateTime, and other like things in Visual Studio but am not getting anywhere.
Looks like you're using the old OLE Automation date. Use
DateTime.FromOADate(myDouble)
Try something like this:-
double d = 40880.051388 ;
DateTime dt = DateTime.FromOADate(d);
Try using var dateTime = DateTime.FromOADate(40880.051388);.
If you need to format it to a string, use dateTime.ToString("M/d/yyyy H:mm", CultureInfo.InvariantCulture) for that. That will give you 24-hour string (change H to h for a 12-hour system).
If you need greater precision (by a factor 1000 or more) than offered by FromOADate, see my answer in another thread.
The value is an offset in days from December 30th, 1899. So you want:
new DateTime(1899, 12, 30).AddDays(40880.051388)
The following simple code will work
DateTime.FromOADate(myDouble)
However if performance is critical, it may not run fast enough. This operation is very processor intensive because the range of dates for the OLE Automation Date format begins on 30 December 1899 whereas DateTime begins on January 1, 0001, in the Gregorian calendar.
FromOADate calls a DoubleDateToTicks function using myDouble as the only argument. This returns the number of ticks, and this value is used to create a new DateTime with unspecified DateTimeKind.
The vast bulk of this work is done by the DoubleDateToTicks function in mscorlib. This includes code to throw an ArgumentException when the value of the double is NaN, and there are numerous ways in which it can be performance optimized depending on your exact needs.
Does anyone possibly recognize the following value "40195.315752" as a date? I need to convert/format this value-based date to a System.DateTime object, but don't understand it's format.
Thanks.
It's a serial date-time, which means it's the number of days since a particular date. Note that you need to know the date which it is an offset to. In Excel, that would be Jan 1st, 1900, which makes your date 17/01/2010 07:34:41, but other programs will vary.
Another common start date is 1st January 1970 (Unix Epoch).
enjoy it:
DateTime.FromOADate(40195.315752).ToLongDateString()
and to convert it to DateTime
DateTime MyDateTime = DateTime.FromOADate(40195.315752);
It means Sunday,January 17 2010
That would possibly be the number of days since a certain date (possibly january 1st 1900), before the decimal point?
the value you have displayed is a double...
var val = 40195.315752;
var span = System.TimeSpan.FromMilliseconds(val);
var time = new DateTime(span.Ticks);
above will convert it to Datetime but besure to note that System.Timespan continas several overloads to load span you need to identify which one is that you want...