How can ı convert datetime to smalldatetime in c# ? I'm taking the date and ı need to convert it to be accordance with database. It is forbidden to change the datatype of column in sql.
You can use the .NET DateTime type for your entity framework model, but tell EF that it uses a non-default column type in the database. You do this by overriding the OnModelCreating method of your DbContext, and using the HasColumnType method:
public class Foo
{
public int Id { get; set; }
public DateTime IAmSoSmall { get; set; } // wants to be smalldatetime in SQL
}
public class MyContext : DbContext
{
public DbSet<Foo> Foos { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var foo = modelBuilder.Entity<Foo>();
foo.Property(f => f.IAmSoSmall).HasColumnType("smalldatetime");
base.OnModelCreating(modelBuilder);
}
}
Of course, you'll have to do the appropriate range-checking on your DateTime property to be sure that the stored values fall between those supported by SQL's smalldatetime. I guess you could do that with a property attribute like:
[Range(typeof(DateTime), "1/1/1900", "6/6/2079")]
public DateTime IAmSoSmall { get; set; } // wants to be smalldatetime in SQL
...based on a valid range from January 1, 1900, through June 6, 2079, as documented on MSDN.
Sql Server datetime and smalldatetime are both automatically mapped to and from the CLR's System.DateTime. A smalldatetime has a precision of 1 minute; a datetime has a precision of approximately 1/300 of a second (Don't ask why. It just is). Since the CLR's System.DateTime1 has a precision of 100-nanoseconds, the runtime takes care of rounding.
smalldatetime is internally a 32-bit integer, containing a count of minutes since the smalldatetime epoch (1900-01-01 00:00).
In conversion, seconds and fractional seconds are rounded using SQL Server's arcane date/time rounding rules, so the date 2013-01-31 23:59:59 gets rounded to the next date 2013-02-01 00:00:00'.
datetime is a pair of 32-bit integers internally. The high-order word is a count of days since the epoch; the low-order word is a count of milliseconds since start-of-day (00:00:00). The epoch of a datetime is 1900-01-01 00:00:00.000.
And again, values are rounded in the conversion in the same arcane way, with franctional seconds getting placed into one of the appropriate millisecond buckets for SQL Server, a multiple of 3ms — there is no SQL Server `datetime value like 2013-05-01 13:57:23.004. That will get "rounded" to either 23.003ms or 23.006ms.
If you want more control over things, you'll need to adjust your datetime values in C# before sending them to the database.
Maybe you can do something like YourDateTime.Date
Normally, when you do that way, it will set time to 00:00:00.
Related
The CosmosDB database I am using suggests I store DateTime in a string.
Working with Dates in Azure Cosmos DB
So I am trying to do this:
string DateAndTime = DateTime.Now.ToString()
but it's not giving me the correct format. Is there a method to do this and to convert it to this exact format: YYYY-MM-DDThh:mm:ss.sssZ ?
If you're not already using the DocumentClient, you could use this to interface with your collection.
Using the DocumentClient means that you can define your document types as you wish, without having to manually convert fields to string. For example, you could use the following type to create/query documents out of the collection:
public class CosmosDocument
{
[JsonProperty("id")]
public string Id { get; set; }
public DateTime TimeStamp { get; set; }
}
The DocumentClient will then serialize/deserialize/model-bind the data, including DateTime values for you.
The serialization is configurable if you need to make any changes to the default settings.
EDIT
As noted in the comments, CosmosClient is the newer version that provides the same functionality described above.
According to Custom date and time format strings, you should use something like that
string DateAndTime = DateTime.Now.ToString("yyyy-MM-ddThh:mm:ss.sssz");
It will give you the following string 2020-04-04T11:19:06.06+3
yyyy means four-digit year (YYYY format doesn't exist), dd represents the day of the month (from 01 to 31). z is used for offset between your local time zone and UTC
The capital Z literal in string indicates that datetime is in UTC format (according to ISO 8601 standard). To get it literally in a result string you may use DateTime.UtcNow instead of DateTime.Now with Z literal or K specifier at the end
string DateAndTime = DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ss.sssK");
It gives you 2020-04-04T08:49:22.22Z (current datetime in UTC format). K specifier will add Z literal for UTC dates and offset (in zzz format) for local dates
This question already has answers here:
Milliseconds in my DateTime changes when stored in SQL Server
(4 answers)
Closed 7 years ago.
I save a datetime using C# Entity Framework, and when I load that time back from the database, the time varies from the value that I saved by 1 or more milliseconds.
Here is the C# Code:
public List<DateTime> TestDate()
{
var dates = new List<DateTime>();
DateTime testvalue = DateTime.Now;
dates.Add(testvalue);
IactexGMG2Entities firstContext = new IactexGMG2Entities();
var firstQuery = from p in firstContext.LocationProperties
where p.locationPropertyId == 4
select p;
var firstRec = firstQuery.Single();
firstRec.locationPropertyDateTime = testvalue;
firstContext.SaveChanges();
firstContext.Dispose();
IactexGMG2Entities secondContext = new IactexGMG2Entities();
var secondQuery = from p in secondContext.LocationProperties
where p.locationPropertyId == 4
select p;
var secondRec = secondQuery.Single();
var secondDate = secondRec.locationPropertyDateTime ?? DateTime.Now;
dates.Add(secondDate);
secondContext.Dispose();
return dates;
}
Here are the received values:
5/29/2015 5:43:25 PM . 154 , 635685182051540566
5/29/2015 5:43:25 PM . 153 , 635685182051530000
Here is the razor code that displays the values:
#foreach (var date in Model)
{
counter++;
<div>
#date . #date.Millisecond , #date.Ticks
</div>
}
As you can see, the second value, which was read back from the database, is lower than the first value by 1.0566 milliseconds.
The amount of variation varies, positive and negative, always with a small number of milliseconds.
Does anyone know how the conversion between the date values takes place?
Note: If I use the same context to read the date value, the values match. I assume that is because it is using the cached value, rather than the SQL Server value.
The problem is the different resolution between TSQL datetime and .NET DateTime data types
datetime only has a small resolution and is rounded to increments of .000, .003, or .007 seconds, whereas DateTime has a resultion of 100ns
Just use the new datetime2 SQL Data Type, which has the same resolution as .NET's DateTime, which is anyway recommended in new work, exactly for the issue you noticed
This actually has very little to nothing to do with Entity Framework. SQL Server as of 2008 has two DateTime types:
DateTime
Accuracy : Rounded to increments of .000, .003, or .007 seconds
DateTime2
Accuracy : 100 nanoseconds
Using Code-First Annotations you can set the property type like:
public MyClass
{
[Column(“CreatedOn", TypeName="DateTime2")]
public DateTime CreatedOn { get; set; }
}
Or using Fluent API:
modelBuilder.Entity<MyClass>()
.Property(p => p.CreatedOn)
.HasColumnType("DateTime2");
If I select a date-typed column in sqlite without any functions, it returns me a proper .NET DateTime object:
// Returns .NET DateTime object
select date_column from test_table;
But the moment I use a scalar function, it always returns me a string:
// Returns string
select datetime(date_column) from test_table;
select date(date_column) from test_table;
The reason I need this is for date rounding
// Rounds to month
select datetime(strftime('%Y-%M-01T00:00:00', date_column)) from test_table;
// Rounds to year
select datetime(strftime('%Y-01-01T00:00:00', date_column)) from test_table;
I tried implementing my own SQLiteFunction, but it still returns a string:
[SQLiteFunction(Name="round_date")]
public class RoundDate : SQLiteFunction
{
/// <summary>
/// Expects 2 arguments:
/// 1: date
/// 2: rounding (Month, Quarter, Year)
/// </summary>
public override object Invoke(object[] args)
{
DateTime date = SQLiteConvert.ToDateTime(args[0].ToString());
DateTime result = date;
switch (args[1].ToString())
{
case "Month":
result = new DateTime(date.Year, date.Month, 1);
break;
case "Quarter":
int quarter = (date.Month-1)/3;
var quarterStart = quarter*3 + 1;
result = new DateTime(date.Year, quarterStart, 1);
break;
case "Year":
result = new DateTime(date.Year, 1, 1);
break;
}
// function returns a DateTime object.
// But executing the statement returns a string
return result;
}
}
// Uses custom function, but still getting String
select round_date(date_column, 'Year') from test_table;
I know I can typecast/convert the string result manually.
But is there any way to force the select statement to return a DateTime object automatically?
[Edit 1]
I understand that Dates and DateTimes are not one of the natively-supported data types in sqlite.
I also know that I can manually convert the formatted strings to DateTime objects.
However, select date_column from test_table actually returns .NET DateTime objects. I assume the System.Data.SQLite implementation does this conversion automatically.
var selectStmt = sqlite.CreateCommand();
selectStmt.CommandText = "select date_column from test_table";
// ==============================
// ==============================
// Returns System.DateTime object
var this_is_a_DateTime_object = selectStmt.ExecuteScalar();
// ==============================
So I was expecting this same behaviour when using date(), datetime(), and my own SQLiteFunction implementation.
I don't believe there's a way to force the System.Data.Sqlite to automatically return the .NET DateTime datatype for you in this instance. Here's what's happening. Let's say your table definition looks like this:
CREATE TABLE test_table (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
date_column DATETIME NOT NULL
)
As you already noted, there's really no such thing as a data type in SQLite. But, as you also noted, the library is clearly handing you a native DateTime value back in this instance. My guess is the same as yours: it's using the semi-arbitrary wording of DATETIME as your request to undertake this helpful conversion on your behalf.
To test this, I added a clearly invalid date into one of my DATETIME columns and the library threw the exception "String was not recognized as a valid DateTime".
Now, to answer your question of why you don't get this same benefit using one of the date/time functions, the answer lies in the documentation:
Notice that all other date and time functions can be expressed in terms of strftime():
date(...) strftime('%Y-%m-%d', ...)
time(...) strftime('%H:%M:%S', ...)
datetime(...) strftime('%Y-%m-%d %H:%M:%S', ...)
julianday(...) strftime('%J', ...)
The only reasons for providing functions other than strftime() is for convenience and for efficiency.
So you're not really calling date/time functions. You're calling a formatting function whose return time is--you guessed it--a string. I made a few failed attempts myself at trying to cast the result of a function back to a datetime, like so:
select (date(...) as DATETIME), ...
But unfortunately, you can only typecast to one of SQLite's native storage classes using the type affinity name (one of: NONE, TEXT, REAL, INTEGER, or NUMERIC).
So it looks like you're back to having to take care of the conversion yourself after the fact. (As will I.)
As stated before, you can build a table with DATETIME type for a column, which returns a DateTime datatype in .NET.
Once you use any of the internal functions or Custom SQLiteFunctions it reverts it to an internal (non-date) data type.
There is a funny hack that can be used if you really want to avoid the String data type, this appears to be the ONLY way I can force it to return a DateTime data type in .NET after some level of date manipulation (so far). And I'm not really keen on it myself...
If you define a table like such...
CREATE Table test2(id bigint, name nvarchar(500), DT datetime)
The query result of the third column is a DateTime.
So following the below logic (again this is ugly, but maybe will inspire someone with more ideas) will return a date time that has been modified by the internal datetime function...
CREATE TABLE output (id bigint, name nvarchar, dt datetime)
;
INSERT INTO output
SELECT id, name, DateTime(dt,'+5 years') FROM Test2
;
SELECT * FROM output
;
DROP TABLE output
Executing this as a single statement will fill one datatable with the result as expected DateTime Datatype in column 3, shifted by 5 years.
In your code if you can use a unique output table name for each call then the approach is safe from conflict with multiple statements.
In SQLite databases there are no storage data type for "Date and time"
You can convert the datatype after a SELECT command to standard .Net DateTime format.
Query : "SELECT ID, DateModified FROM Customer"
string id = reader.GetInt64(0).ToString();
DateTime dateTime = (DateTime)reader[1];
SOURCE: http://techreadme.blogspot.de/2012/11/sqlite-read-write-datetime-values-using.html
I'm sorry the above information applies to SQLite versions 1 & 2. SQLite3 does include datatypes although they are implemented differently than Standard SQL Databases.
https://sqlite.org/datatype3.html
I don't use SQLite but, from what I've read, there is no native data type for dates and times. If your original query is producing a result set that the SQLite ADO.NET provider interprets as .NET DateTime values then I can only assume that it is based on format. In that case, you might be able to use strftime to output in that same format and get the data as DateTime values automatically. It appears that that format may be "yyyy-MM-dd HH:mm:ss.fff" in .NET terms.
I have a MVC3 application in which i want to set a timespan to for example 2 days and 5 hours.
when i enter 02:05:00:00 it gives me the following exception:
System.OverflowException: SqlDbType.Time overflow. Value '2.05:00:00' is out of range. Must be between 00:00:00.0000000 and 23:59:59.9999999.
When i enter 05:00:00 it correctly saves 5 hours into the database. according to MSDN timespan has a property for days. How do i correctly set the days?
Model:
public class ProductionTimeVM
{
[Required]
public TimeSpan DefaultTime { get; set; }
}
In my view i just use:
#Html.TextBoxFor(x => x.DefaultTime)
For my controller:
public ActionResult SaveProductionTime(ProductionTimeVM vm)
{
ProductionTime productionTime = new ProductionTime();
productionTime.Default = vm.DefaultTime;
//some more code
}
Any idea's?
You are probably saving a TimeSpan value to column with Time datatype in database. Time can only express a time of day, so you can't save TimeSpans larger than a day.
I use columns with bigint data type to store and retrieve ticks of TimeSpan. I would also like to know if there is a better alternative. This behavior is like default for some popular ORMs and it's misleading a lot of people I think.
I'm having an issue with saving and retrieving dates with Mongo using the c# driver. For some reason it it's truncating the ticks.
When I store this:
DateTime -> 5/17/2011 7:59:13 PM
Ticks -> 634412591533741650
I get this back:
DateTime -> 5/17/2011 7:59:13 PM
Ticks -> 634412591533740000
So if I try to do:
serverDateTime == mongoDateTime
It always fails. Anyway around this?
The reason is that the BSON DateTime format stores values with less precision than a .NET DateTime value, so when you read it back from the database the value has been truncated.
If your DateTime value is a property of a C# class you are serializing you can ask the serializer to serialize the DateTime value as an embedded document containing both the BSON DateTime value (truncated) and the original .NET DateTime value (stored as Ticks). In that case the value will not be truncated when deserialized.
For example:
public class MyClass {
public ObjectId Id;
[BsonRepresentation(BsonType.Document)]
public DateTime MyDateTime;
}
You can also use a BsonRepresentation of Int64 or String and not lose precision, but then the stored document only has Ticks or a string representation and no BSON DateTime, which makes it hard to do DateTime related queries.
You'll also want to keep in mind that DateTime values are stored in UTC in the database. The best practice is to always use UTC values for storage and only use local times when displaying them to the user.
Here's an extension you could use :)
public static class MongoDateComparison
{
private static int precisionInMilliseconds = 1000;
public static bool MongoEquals(this DateTime dateTime, DateTime mongoDateTime)
{
return Math.Abs((dateTime - mongoDateTime).TotalMilliseconds) < precisionInMilliseconds;
}
}