Working with dates in breeze - breeze

I'm having some trouble working with dates.
I have an object with a date field:
public DateTime FechaInicio{get; set;}
This definition generates the following field in the database:
FechaInicio datetime not null
Making the request to the web service I get the date ( in the JSON ) in the following format:
"FechaInicio": "1982-12-02T00: 00:00"
And calling FechaInicio() on tne entity returns a javascript Date object.
Creating a new entity I get the following value:
createPalanca var = function () {
MetadataStore var = manager.metadataStore;
metadataStore.getEntityType palancaType = var ("Toggle");
palancaType.createEntity newPalanca = var ();
manager.addEntity (newPalanca);
//Here: newPalanca.FechaInicio () has the value in this format: 1355313343214
//Expected Date object here
newPalanca return;
};
After all, my real question is: What format should I use to assign new values ​​to date type fields?
Edit:
After doing some tests, I noticed that if I assign a Date object to the property, everything seems fine until we got to this line:
saveBundleStringified var = JSON.stringify (saveBundle);
saveBundle content is:
FechaInicio: Thu Dec 20 2012 00:00:00 GMT+0100 (Hora estándar romance)
and the saveBundleStringified:
"FechaInicio": "2012-12-19T23:00:00.000Z" <- I guess this is utc format
What finally is stored in the database is: 2012-12-19 23:00:00.0000000
When the result of the call to SaveChanges are returned , they are merged with the entities in cache at the function updateEntity which does this check: if (!core.isDate(val)) that returns false.
As a consequence it is created a new Date object with the wrong date:
function fastDateParse(y, m, d, h, i, s, ms){ //2012 12 19 23 00 00 ""
return new Date(y, m - 1, d, h || 0, i || 0, s || 0, ms || 0);
}
Correct me if I'm wrong, but I think that's the problem.

Sorry for taking so long...
There were bugs with Breeze's DateTime timezone serialization and the default DateTime values used for newly constructed entities with non-nullable date fields. These are fixed as of v 0.77.2. Please confirm if this set of fixes works for you.
And thanks for finding these.
And to answer your question, all date properties on your object should be set to javascript Dates. Breeze should handle all of the serialization issues properly.

Dates always scare me. My immediate instinct is that the browser and server are not on the same TimeZone; how that could be I don't know. In any case, it's bound to happen and I recall all kinds of fundamental problems with coordinating client and server on datetime. I think the usual recommendation has always been to keep everything in UTC and adjust what you display to the user in local time.
I rather doubt this is a helpful answer. I'm not sure what part Breeze should play in resolving this. Would welcome a suggestion that we can circulate and build consensus around.
Also can you clarify this statement:
When the result of the call to SaveChanges are returned , they are merged with the entities in cache at the function updateEntity which does this check: if (!core.isDate(val)) that returns false. As a consequence it is created a new Date object with the wrong date
What do you mean by "the wrong date"? And are you saying that Breeze thinks the incoming date value is in an invalid format (as opposed to being a date other than the one you expected)?
Yes, #Sascha, Breeze is using the Web Api standard for JSON formatting (Json.Net) and it is set for ISO8601 format as opposed to the wacky Microsoft format (which escapes me as I write this).

Breeze/Web Api seem to need the dates in some special format (ISO8601). Any other format did not work for me. moment.js solved the problem for me with setting and reading. Formatting is also nicely done if you use Knockout to display the date with a special binding.
entity.someDate(moment().utc().toDate()) // example
and it works.
You could also use this:
Date.prototype.setISO8601 = function(string) {
var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
"(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
"(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
var d = string.match(new RegExp(regexp));
var offset = 0;
var date = new Date(d[1], 0, 1);
if (d[3]) {
date.setMonth(d[3] - 1);
}
if (d[5]) {
date.setDate(d[5]);
}
if (d[7]) {
date.setHours(d[7]);
}
if (d[8]) {
date.setMinutes(d[8]);
}
if (d[10]) {
date.setSeconds(d[10]);
}
if (d[12]) {
date.setMilliseconds(Number("0." + d[12]) * 1000);
}
if (d[14]) {
offset = (Number(d[16]) * 60) + Number(d[17]);
offset *= ((d[15] == '-') ? 1 : -1);
}
offset -= date.getTimezoneOffset();
time = (Number(date) + (offset * 60 * 1000));
this.setTime(Number(time));
};

Related

Dart: Comparing two times from string

Is there any way to compare two times in dart, suppose we have: 13:45 and 15:34, is there any way to find out that 15:34 is after 13:45.
I was looking at this question, and there are functions to check isBefore or isAfter, but is it possible to parse time without having to parse year, month and day?
You can convert them to datetime and compare. ie:
void main() {
var s1 = '13:45';
var s2 = '15:34';
var t1 = DateTime.parse('2000-01-01 ${s1}');
var t2 = DateTime.parse('2000-01-01 ${s2}');
print(t1.isBefore(t2));
}
EDIT: For a more direct, string sort like comparison (which I wouldn't suggest at all for Date\time values, unless you are 100% sure they are in sortable format) you could use compareTo(). ie:
print(s1.compareTo(s2) < 0);

Conditionals inside Where Clause of LINQ

I want to fine-tune the results in the controller action with a few parameters coming from client.
I was following this answer.
The problem is the logs variable returns no results even if all the parameters are not there (I expect it to return all the records). It works perfectly fine I do
return View(db.Logs.ToList());
But my implementation of the answer by Darren Kopp doesn't return anything at all. My code:
Category cat;
DateTime startDate;
DateTime endDate;
var logs = from log in db.Logs
select log;
if (Enum.TryParse<Category>(viewModel.Category, out cat))
logs = logs.Where(l => l.LogCategory == cat);
if (DateTime.TryParse(viewModel.StartDate, out startDate))
logs = logs.Where(l => l.TimeStamp >= startDate);
return View(logs.ToList());
I am using VS 2015 & this is MVC 5. What is causing the problem?

Kendo Timepickerfor formatting not working

I have an MVC Kendo Timepicker for that I am using. It works fine except that I can't format the time to Military time. After I add the formatting for Military time, once I select the time the validation doesn't pass and it tells me it must be a date. Is there a way to format the TimePickerFor to allow military time?
#using Kendo.Mvc.UI
#model DateTime?
#(Html.Kendo().TimePickerFor(m=>m)
.Value(#Model)
.Min("05:00")
.Max("00:00")
.Format("{0:HHmm}")
)
Update: This doesn't work with format being changed to .Format("HHmm")
Ok, so thanks to the Kendo people, I found the answer. The script may need some work depending on the situation. My TimePickerFor is in an Editor Template which sits in a grid with other timepickers and numeric text boxes. Only thing with this way of working is that once the script is fired, the numeric boxes used this script also to validate (hence the return $.isNumeric(input.val()) line. Hope this helps someone else out.
TimePickerFor Control:
#using Kendo.Mvc.UI
#model DateTime?
#(Html.Kendo().TimePickerFor(m=>m)
.Value(#Model)
.Format("HHmm")
.HtmlAttributes(new{data_format="HHmm"})
.ParseFormats(new[]{"HHmm"})
)
<script>
var originDate = kendo.ui.validator.rules.mvcdate;
kendo.ui.validator.rules.mvcdate = function(input) {
var format = input.attr("data-format");
if (input.val() == "") {
return kendo.parseDate("0000", format);
}
if (format) {
return kendo.parseDate(input.val(), format);
} else {
return $.isNumeric(input.val());
}
};
</script>
I think you have to remove the curly braces and make sure that is a valid format type. I also don't think the 0 is necessary.
Here's some formating documentation
http://docs.telerik.com/kendo-ui/getting-started/framework/globalization/dateformatting
#(Html.Kendo().TimePickerFor(m=>m)
.Value(#Model)
.Min("05:00")
.Max("00:00")
.Format("yyyy/MM/dd hh:mm tt")
)
Edit:
Is your max and min values correct? I don't see how that is logically correct.

Passing query parameters in Dapper using OleDb

This query produces an error No value given for one or more required parameters:
using (var conn = new OleDbConnection("Provider=..."))
{
conn.Open();
var result = conn.Query(
"select code, name from mytable where id = ? order by name",
new { id = 1 });
}
If I change the query string to: ... where id = #id ..., I will get an error: Must declare the scalar variable "#id".
How do I construct the query string and how do I pass the parameter?
The following should work:
var result = conn.Query(
"select code, name from mytable where id = ?id? order by name",
new { id = 1 });
Important: see newer answer
In the current build, the answer to that would be "no", for two reasons:
the code attempts to filter unused parameters - and is currently removing all of them because it can't find anything like #id, :id or ?id in the sql
the code for adding values from types uses an arbitrary (well, ok: alphabetical) order for the parameters (because reflection does not make any guarantees about the order of members), making positional anonymous arguments unstable
The good news is that both of these are fixable
we can make the filtering behaviour conditional
we can detect the category of types that has a constructor that matches all the property names, and use the constructor argument positions to determine the synthetic order of the properties - anonymous types fall into this category
Making those changes to my local clone, the following now passes:
// see https://stackoverflow.com/q/18847510/23354
public void TestOleDbParameters()
{
using (var conn = new System.Data.OleDb.OleDbConnection(
Program.OleDbConnectionString))
{
var row = conn.Query("select Id = ?, Age = ?", new DynamicParameters(
new { foo = 12, bar = 23 } // these names DO NOT MATTER!!!
) { RemoveUnused = false } ).Single();
int age = row.Age;
int id = row.Id;
age.IsEqualTo(23);
id.IsEqualTo(12);
}
}
Note that I'm currently using DynamicParameters here to avoid adding even more overloads to Query / Query<T> - because this would need to be added to a considerable number of methods. Adding it to DynamicParameters solves it in one place.
I'm open to feedback before I push this - does that look usable to you?
Edit: with the addition of a funky smellsLikeOleDb (no, not a joke), we can now do this even more directly:
// see https://stackoverflow.com/q/18847510/23354
public void TestOleDbParameters()
{
using (var conn = new System.Data.OleDb.OleDbConnection(
Program.OleDbConnectionString))
{
var row = conn.Query("select Id = ?, Age = ?",
new { foo = 12, bar = 23 } // these names DO NOT MATTER!!!
).Single();
int age = row.Age;
int id = row.Id;
age.IsEqualTo(23);
id.IsEqualTo(12);
}
}
I've trialing use of Dapper within my software product which is using odbc connections (at the moment). However one day I intend to move away from odbc and use a different pattern for supporting different RDBMS products. However, my problem with solution implementation is 2 fold:
I want to write SQL code with parameters that conform to different back-ends, and so I want to be writing named parameters in my SQL now so that I don't have go back and re-do it later.
I don't want to rely on getting the order of my properties in line with my ?. This is bad. So my suggestion is to please add support for Named Parameters for odbc.
In the mean time I have hacked together a solution that allows me to do this with Dapper. Essentially I have a routine that replaces the named parameters with ? and also rebuilds the parameter object making sure the parameters are in the correct order.
However looking at the Dapper code, I can see that I've repeated some of what dapper is doing anyway, effectively it each parameter value is now visited once more than what would be necessary. This becomes more of an issue for bulk updates/inserts.
But at least it seems to work for me o.k...
I borrowed a bit of code from here to form part of my solution...
The ? for parameters was part of the solution for me, but it only works with integers, like ID. It still fails for strings because the parameter length isn't specifed.
OdbcException: ERROR [HY104] [Microsoft][ODBC Microsoft Access Driver]Invalid precision value
System.Data.Odbc. OdbcParameter.Bind(OdbcStatementHandle hstmt,
OdbcCommand command, short ordinal, CNativeBuffer parameterBuffer, bool allowReentrance)
System.Data.Odbc.OdbcParameterCollection.Bind(OdbcCommand command, CMDWrapper cmdWrapper, CNativeBuffer parameterBuffer)
System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior behavior, string method, bool needReader, object[] methodArguments, SQL_API odbcApiMethod)
System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior behavior, string method, bool needReader)
System.Data.Common.DbCommand.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
Dapper.SqlMapper.QueryAsync(IDbConnection cnn, Type effectiveType, CommandDefinition command) in SqlMapper.Async.cs
WebAPI.DataAccess.CustomerRepository.GetByState(string state) in Repository.cs
var result = await conn.QueryAsync(sQuery, new { State = state });
WebAPI.Controllers.CustomerController.GetByState(string state) in CustomerController .cs
return await _customerRepo.GetByState(state);
For Dapper to pass string parameters to ODBC I had to specify the length.
var result = await conn.QueryAsync<Customer>(sQuery, new { State = new DbString { Value = state, IsFixedLength = true, Length = 4} });

Very odd event behaviour for onChange on Telerik MVC DatePicker

To the question started, my code (I'll try to only include relevant portions to start), starting with my script:
function RaceDate_onChange() {
var pickedDate = $(this).data('tDatePicker').value();
var month = pickedDate.getMonth() + 1;
$.get("/RaceCard/Details?year=" + pickedDate.getFullYear() + "&month=" + month + "&day=" + pickedDate.getDate());
}
Then my markup:
#Html.Telerik().DatePickerFor(model => model.RaceDate).ClientEvents(events => events.OnChange("RaceDate_onChange"))
And finally a bit of the receiving action:
[HttpGet]
public ActionResult Details(int year, int month, int day)
{
var viewModel = new RaceCardModel {Metadata = DetailModelMetadata.Display, RaceDate = new DateTime(year, month, day)};
I'm trying to get the selection of a new date to trigger a GET, to refresh the page without submitting a form. This works fine, except for this problem:
In GET requests to the Details action, the day value is always one day behind the DatePicker. E.g. The first value is set from a view model property, when the view is rendered, say 3. I then click on 14 and hit my breakpoint in the action method. The day value is 3. When I click on 29 and hit the breakpoint, the day value is 14.
Besides asking what is wrong, I'll take a liberty and ask if there is a better way that is no more complicated. I am fairly novice and would rather deliver working code that needs revision than get bogged down in tangents and details.
Try using e.value instead as shown in the client-side events example. You are probably using an older version where the value() method returned the previous value during the OnChange event.
UPDATE:
"e.value" means the value field of the OnChange arguments:
function onChange(e) {
var date = e.value; // instead of datePicker.value()
}
As far as the 1 month difference you are getting, that's normal, and it is how the getMonth() method works in javascript on a Date instance:
The value returned by getMonth is an
integer between 0 and 11. 0
corresponds to January, 1 to February,
and so on.
So adding +1 is the correct way to cope with the situation, exactly as you did.
Just a little remark about your AJAX call: never hardcode urls. Always use url helpers when dealing with urls:
var year = pickedDate.getFullYear();
var month = pickedDate.getMonth() + 1;
var day = pickedDate.getDate();
var url = '#Url.Action("Details", "RaceCard")';
$.get(url, { year: year, month: month, day: day }, function(result) {
// process the results of the AJAX call
});

Resources