Sqlite Net PCL DateTime Precision - c#

I need to save a datetime value with miliseconds precision - e.g.: "11/28/2019 09:59:40.777" - in the table "Journal", I am using a trigger for it.
This is my Model:
public class Journal
{
public int IdAluno { get; set; }
public int IdAulaProfessor { get; set; }
[ForeignKey(typeof(JournalOperacao))]
public int IdOperacao { get; set; }
public DateTime DataHorario { get; set; }
[ManyToOne(CascadeOperations = CascadeOperation.CascadeRead)]
public JournalOperacao JournalOperacao { get; set; }
}
The SQLiteConnection contructor:
SQLiteConnection = new SQLiteConnection(DbFilePath);
The trigger
DbConnection.Execute(#"CREATE TRIGGER IF NOT EXISTS JournalInsertTrigger
AFTER INSERT ON DiarioFalta
BEGIN
INSERT INTO Journal (IdAluno, IdAulaProfessor, IdOperacao, DataHorario) VALUES (new.IdAluno, new.IdAulaProfessor, 1, (strftime('%s', 'now', 'localtime') + 62135596800) * 10000000);
END;");
When the trigger inserts a row, the column "DataHorario" only saves the date and time, but I need the miliseconds too.
I have already tried (julianday('now') - 2440587.5)*86400.0, but the value I get is "1/1/0001 12:00:00 AM"
var journal = JournalData.GetItems();
var row = journal.First();
The value of row is
value = { DataHorario = "1/1/0001 12:00:00 AM", IdAluno = 144600, IdAulaProfessor = 1821540, IdOperacao = 1 }

After writing the initial answer, it wasn't until the end that I perceived your question is lacking sufficient detail. The very last line of the question says "the value I get is..." but you don't actually show how you are getting that value. Also, you show the C# model, but not the SQLite table definition. Ultimately to get a full solution that works correctly both within SQLite and between the C# model, you need to provide more details of how data is being read and converted between the model and the database. I hope my answer helps anyway.
As a reference see the SQLite document page for date and time functions.
Within SQL to get the full date-time string format with millisecond precision requires the complete format string using %f for fractional seconds like SS.SSS. It produces a string like '2019-11-28 10:27:27.146.:
strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime')
Because strftime() primarily returns string values, it is incorrect to apply addition or multiplication. Since SQLite has no native date-time data type, there is no automatic conversion for handling mathematics. There is also no need to manipulate the value since it already has millisecond precision in the last digits like SS.SSS.
The numeric date-time value returned by the function julianday() already contains millisecond precision. For simply storing the date/time value, there is no need to manipulate the value with multiplication or subtraction.
To get the current local time: julianday('now', 'localtime')
To get the corresponding string representation, pass the Julian numeric date/time value to the strftime() function like the following examples:
strftime('%Y-%m-%d %H:%M:%f', julianday('now', 'localtime'))
strftime('%Y-%m-%d %H:%M:%f', julianDayColumn)
strftime('%Y-%m-%d %H:%M:%f', 2458815.93573086)
The Unix epoch format (seconds since 1970-01-01) like strftime('%s', 'now', 'localtime') does NOT keep millisecond precision, only seconds precision... it records only integer seconds without any fractional part.
If I recall correctly (sorry I can't test right now), the official .Net library System.Data.Sqlite will automatically convert between .Net DateTime values and the SQLite string values using standard interfaces, however I'm not sure if this is true for the millisecond precision. Such automatic conversion might require that the table column be declared as DATETIME type.
Whatever the case, you will need to handle the dates within pure SQL differently than the conversion between SQL and .Net/C#. Within SQL (e.g. inside triggers, SQL update and insert statements, etc.) you need to use the SQLite date and time functions. Within C# and the .Net framework, you will want the value converted to the .Net DateTime type. But that conversion likely does not require the forced multiplication and subtraction--those manipulations will usually ruin the date-time values unless you already know exactly what you are doing and for what reason... not just guessing at formats.
If you are trying to following recommendations from other sites, I see various attempts at storing and retrieving ticks and Unix Epoch values, etc. Such attempts will likely ruin the ability to store and manipulate dates within SQL including triggers and will likewise prevent storing millisecond precision.

My only intention was to save a date time with miliseconds precision, but I wasn't getting it because SQLite-Net-PCL creates the column data type table DateTime(C#) as bigint(SQLite) and I was using strftime('%Y-%m-%d %H:%M:%f','now', 'localtime') which returns a string type.
Since I'm not interested in manipulating the column DateTime DataHorario I changed the model column DateTime DataHorario to string DataHorario, which fixed my case.

Related

what should be the datatype of utc_offset capturing using google place api

i am using google api for getting user information in a form, which has a field for timezone. i am binding utc_offset value that getting from google api.this value can be postive or -ve(eg:330 for india and -300 for US). i am using entity framework .so which datatype should i have to use for saving the timezone.
i added one migration with
`public TimeZoneInfo{ get; set; }`
but this column is not updating in db. can any one help me to solve this problem
First TimeZoneInfo is the wrong type. You don't actually know which time zone the user is in, just the offset. An UTC offset can be shared by multiple time zones with different daylight savings rules, etc.
A UTC offset is a duration. The right .NET type is a TimeSpan, but there's no standard SQL type that maps to that. For SQL Server EF will use Time, but you'll get a runtime error if you try to store a duration outside of the interval [0,24 hours).
So the right type for this is simply an int, and you'll need to keep track of the units of measure. So something like:
public int UTCOffsetHours { get; set; }

Datetime conversion giving error

consider me a beginner in c#
I am doing some changes in a pre developed software (C#.Net) , we are saving data by datewise , Currently in insert query (build in c#) we are passing GETDATE() to save today date , but now we have to save data on the basis of a different date.
When I am building query in c# , I m passing that a datetime variable into query
after conversion , conversion as follow
Date_Stamp = DateTime.ParseExact(dt.Rows[0][0].ToString(), "MM/dd/yyyy HH:mm:ss tt", new CultureInfo("en-IN"));
but it is showing error "String was not recognized as a valid DateTime.".
The reason to convert is coz these date field are getting displayed in format ToString("yyyy-MM-dd"));
Which will give 2017-07-13 14:56:30.233 as 13-jul-2017 on front end (as per requirement). We cant change this part of code as it is being used in lot of places , hard to change .
Problem is
variable storing value as
2017-12-07 00:00:00.000
which give after conversion 07-Dec-2017 [wrong - it is needed as 12-jul-2017]
GETDATE storing value as
2017-07-12 14:56:30.233
which is after conversion coming right as 12-jul-2017
I know there is no datetime format in sql server when it come to storing data
But can we store value from variable [2017-12-07 ] as [2017-07-12 ] ?
How GETDATE() give us date in year-month-date format
?
Neither .NET's nor SQL Server's date related type have any format. All of them are binary values, just like integers and decimals. Formats apply only when they are explicitly or implicitly converted to strings, or parsed from strings.
Assuming your query looked something like SELECT GETDATE(), ... and you loaded the results to an DataTable, the values will be returned as DateTime values. If you used a strongly-typed DataTable you could just use the value. With a generic DataTable the value will be boxed and return as an object.
All you have to do is just cast the field value to DateTime :
Date_Stamp = (DateTime)dt.Rows[0][0];
This will also work for date and datetime2 types. datetimeoffset is returned as DateTimeOffset. time is returned as TimeSpan.
The problem in the original is caused because the field value is formatted into a string using the current culture dt.Rows[0][0].ToString() first. Then ParseExact is called trying to parse it using a different format. A simple DateTime.Parse(dt.Rows[0][0].ToString()) would have worked (even though it would be wasteful), since both DateTime.Parse and DateTime.ToString() use the same culture.
UPDATE
Reading date fields from a table has no issues - the values are returned using the appropriate date type. For example, running SELECT StartDate from ThatTable will return DateTime if the table's schema is :
CREATE TABLE ThatTable
(
ID int,
StartDate datetime
)
Problems are caused if, instead of using the correct type, dates are stored as strings in VARCHAR columns. That's a serious bug that needs to be fixed. There is NO assurance that the strings can be parsed to dates at all, or that they follow the same format. It's all too easy for some faulty application code to use eg DateTime.Now.ToString() and store a localized string in there.
Even if the format is the same, it's just wasteful and unreliable. The string takes more storage than the equivalent type, introduces conversion issues, prevents the use of date functions, and the server can't apply date optimizations to queries and indexing.

How to format a Date into SQL server using EntityFramework

I'm trying to storage into my database ONLY the DATE not DATE AND TIME, only Date, but it always came with the time together.
This is how I do to storage only the date inside of String :
string.Format("{0:dd/MM/yyyy}", DateTime.Now)
And works fine, but now, I want to storage a StringDate to a Date in my SQL Server database. So I did this :
EntityTable...
[Column(TypeName = "date")]
public DateTime? InicialDate { get; set; }
Controller
InicialDate = DateTime.ParseExact("01-12-2016",
"dd/MM/yyyy",
new CultureInfo("pt-BR"));
And inside of my Table, the Date is not at the right format as I expected, I came like this :
2017-12-01 and not, DAY-MONTH-YEAR....
And if I try to make a query and retrieve the date, i came like this :
"InicialDate": "2017-12-01T00:00:00"
I just want to save ONLY the DATE without time!
Correct way is creating your Date type for using whole project. Also there is some Data class already developed: https://github.com/claycephas/csharp-date
If you've already created the table with [Column(TypeName = "date")], please check the schema and data of the table, the type of column InicialDate should be date, which doesn't save the time portion of datetime.
The time portion you saw in the result (i.e. T00:00:00) was appended by EF, when it was cast to DateTime structure.
DateTime is internally just a single number (probably an int/long, representing the number of seconds since the Epoch; not sure about this, though; but it doesn't really matter here) and how it's displayed as a string depends on the format used. DateTime.ParseExact("01-12-2016", "dd/MM/yyyy", new CultureInfo("pt-BR")); parses the date into DateTime internal representation according to the pt-BR rules for displaying date, then when EF is posting this to the db it converts the internal representation to ISO-8601 textual form (because SQL is text-based), then the db engine again converts it into a number form and stores it. When you look in the db, you see it as 2017-12-01, because the tool you use to do this is set up to display dates in the ISO-8601 format.
So, the date is stored correctly, what you seed depends on the format the particular app uses to display dates.
Change DateTime to nvarchar(10) in database if u use DateTime in database 00.00.00 will be automatically assigned by database. So, you are getting time with it while retrieving.
Change column datatype to Varchar issue will be resolved.
Sincerely,
Thiyagu Rajendran
**Please mark the replies as answers if they help and unmark if they don't.

Need C# to save date into sql server as sql server datetime e.g. 2016-05-19 12:46:08.610

I need to have C# via Entity Framework save current datetime to sql server into table column of datatype datetime
Was reading that DateTime.Now in C# is not going to be correct ...
so I stumbled across where a guy posted that he was doing this as it saves down to the proper millisecond
System.Data.SqlTypes.SqlDateTime entry2
= new System.Data.SqlTypes.SqlDateTime(new DateTime(dto.LookUpDateTime));
DateTime entry = entry2.Value;
Now I assumed with the Overloads that I should be able to just do this:
System.Data.SqlTypes.SqlDateTime dt
= new System.Data.SqlTypes.SqlDateTime(new DateTime());
However, I get an error in catch block saying 'sqldatatime overflow...`
DateTime dateTime = dt.Value;
rpmuser.lst_pwd_chg_dtm = dateTime;
rpmuser.cre_dtm = dateTime;
Can I use DateTime.Now or what do I need to do to get this SqlDateTime to work?
This is almost certainly because you are trying to store a date that is outside the supported range. On MS SQL Server the datetime field type can hold datetime values in the range 1-Jan-1753 00:00:00 to 31-Dec-9999 23:59:59.997 inclusive. This is narrower than the range explicitly supported by the .NET DateTime type (1-Jan-0001 00:00:00 to 31-Dec-9999 23:59:59 plus a fraction). So any date prior to 1-Jan-1753 will cause that error.
A common problem is when you use either DateTime.MinValue to indicate a specific state of your data but don't filter that to something the SQL field can contain before sending the data to the database. The solution in this case would be to define a suitable lower boundary of the data and define a static value that is lower but still within the SQL range.
If your data needs to include dates and times outside of the valid range for the SQL datetime field type then you might want to use the datetime2 field type which has the same effective range as the .NET DateTime type. Which is unsurprising since it appears to be the same data structure - count of 100ns ticks since 1-1-1.

How to pass datetime from c# to sql correctly?

I have a table and the date-times in it are in the format:
2011-07-01 15:17:33.357
I am taking a c# DateTime when I do a .ToString() on the object I am getting a DateTime in the format:
04/07/2011 06:06:17
I'm wondering how I correctly pass the correct DateTime through because when I run the SQL that is in our code it doesn't work (i.e. select the correct DateTime). I can't use SQL profiler.
This is the code:
//looks to if a user has had any activity in within the last time specified
public bool IsUserActivitySinceSuppliedTime(int userId, DateTime since)
{
//get everything since the datetime specified [usually 5 hours as this is
//how long the session lasts for
string sql = "SELECT * FROM tbl_webLogging WHERE userid = #userid AND DateAdded > #sinceDateTime";
SqlParameter sinceDateTimeParam = new SqlParameter("#sinceDateTime", SqlDbType.DateTime);
sinceDateTimeParam.Value = since;
SqlCommand command = new SqlCommand(sql);
command.Parameters.AddWithValue("#userid", userId);
command.Parameters.Add(sinceDateTimeParam);
using (SqlDataReader DataReader = GetDataReader(command))
{
if (DataReader.HasRows)
{
return true;
}
else
{
return false;
}
}
}
UPDATE*******************
I have run the following on the data:
SELECT * FROM tbl_webLogging
WHERE userid = 1
AND DateAdded > '2011-07-01 07:19:58.000'
And
SELECT * FROM tbl_webLogging
WHERE userid = 1
AND DateAdded > '04/07/2011 07:19:58'
One returns 53 records the other returns 69 records. How can this be? And when I pass the DateTime (04/07/2011 07:19:58) from c# to SQL no records show up at all!
You've already done it correctly by using a DateTime parameter with the value from the DateTime, so it should already work. Forget about ToString() - since that isn't used here.
If there is a difference, it is most likely to do with different precision between the two environments; maybe choose a rounding (seconds, maybe?) and use that. Also keep in mind UTC/local/unknown (the DB has no concept of the "kind" of date; .NET does).
I have a table and the date-times in it are in the format: 2011-07-01 15:17:33.357
Note that datetimes in the database aren't in any such format; that is just your query-client showing you white lies. It is stored as a number (and even that is an implementation detail), because humans have this odd tendency not to realise that the date you've shown is the same as 40723.6371916281. Stupid humans. By treating it simply as a "datetime" throughout, you shouldn't get any problems.
I had many issues involving C# and SqlServer. I ended up doing the following:
On SQL Server I use the DateTime column type
On c# I use the .ToString("yyyy-MM-dd HH:mm:ss") method
Also make sure that all your machines run on the same timezone.
Regarding the different result sets you get, your first example is "July First" while the second is "4th of July" ...
Also, the second example can be also interpreted as "April 7th", it depends on your server localization configuration (my solution doesn't suffer from this issue).
EDIT: hh was replaced with HH, as it doesn't seem to capture the correct hour on systems with AM/PM as opposed to systems with 24h clock. See the comments below.

Categories