Validate Datetime on the client

Asked

Viewed 4,561 times

5

I have a model with a property like DateTime:

[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
[DataType(DataType.Date, ErrorMessage="Data em formato inválido")]
public DateTime? Date {get;set;}

And in the View:

@Html.TextBoxFor(model => model.Date)
@Html.ValidationMessageFor(model => model.Date)

When typing a date with the following value: 11/11/1111, is the value not the format, and I send the POST, it passes ModelState, but in the SaveChange causes error:

The Conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value. The statement has been terminated.

What I’ve done so far and haven’t succeeded:

1 - In my Web.config the following attribute:

 <globalization uiCulture="pt-BR" culture="pt-BR" enableClientBasedCulture="true" requestEncoding="UTF-8" responseEncoding="UTF-8" fileEncoding="UTF-8" />

2 - Installation of the jQuery globalize and jQuery Validate globalize. The loading order is this:

<script src="~/Scripts/libs/jquery.globalize/globalize.js"></script>
<script src="~/Scripts/libs/jquery.globalize/cultures/globalize.culture.pt-BR.js"></script>

<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
<script src="~/Content/Scripts/libs/jquery.validate/jquery.validate.globalize.min.js"></script>

3 - Treatment of number and dates using jQuery Validate + globalize, with the following code:

jQuery.extend(jQuery.validator.methods, {
    date: function (value, element) {
        return this.optional(element) || /^\d\d?\/\d\d?\/\d\d\d?\d?$/.test(value);
    },
    number: function (value, element) {
        return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(value);
    }
});

How to validate this date entry or create a "range" on the client and not on the server?

  • As dumb as it is, I had a similar problem that was solved by switching from @Html.Textboxfor(model => model.Date) to @Html.Editorfor(model => model.Date)

  • @Rafaelbarbosa so it is, but I use Textboxfor because of my datepicker plugin...using Editorfor does not work..

  • By the way, he even opens my datepicker, but then also opens the Html5 and does not arrow the values with my datepicker, rs

  • @Rafaelbarbosa actually kkk using the datepicker of Html5 itself worsens the situation, it does not even accept the format I pass, always speaking the field .. must be a date

  • @Rod What is the value defined on the date before the SaveChanges?

  • @Ciganomorrisonmendez in question has the value, which is 11/11/1111, I know it is a little improbable, but it is that there is always a user who wants to fill for test everything with 11 or single value 22...

Show 1 more comment

3 answers

2


@Rod, your problem here is not validation of Type DateTime, but the range allowed by the type DateTime in the SqlServer.

To resolve this issue, you can change the column type in Sqlserver to datetime2(7), which is even the recommended type for new Tables.

Or you can put a Dataannotations to validate the Range so it looks similar to Sqlserver

[DataType(DataType.DateTime, ErrorMessage="Isto não é um data")]
[Range(typeof(DateTime), "01/01/1753", "31/12/9999")]
public DateTime Date { get; set; }
  • I made a Convention that all datetime generates datetime2 thanks was that

1

The problem in . NET

The translation of:

The Conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.

It would be something like:

Conversion of date type "datetime2" to "datetime" resulted in a value outside range/range.

The interval shall be equal to or greater than "January 1, 1753" as per msdn Date and Time Data.

These data types only support Dates that occur after the Introduction of the Gregorian Calendar in England in 1753.

EN: These data support only dates that occur after the introduction of the Gregorian calendar in England in 1753.

Validation on the front end:

I will assume that in 11/11/1111 be it dia/mes/ano, standard used in Brazil, the code should look something like:

date: function (value, element) {
    var data, dataObjeto, ano;

    if (this.optional(element) || /^\d{2}\/\d{2}\/\d{4}$/.test(value)) {
        data       = value.split("/");
        dataObjeto = new Date(data[2], data[1] - 1, data[0]);
        ano        = dataObjeto.getFullYear();

        return (
            ano == data[2] &&
            dataObjeto.getMonth() === parseInt(data[1]) &&
            dataObjeto.getDate() === parseInt(data[0]) &&
            ano > 1900 && ano < 2100
        );
    }
    return false;
}

I’ll explain the code:

  • data = value.split("/"); divides the date that is a string
  • dataObjeto = new Date(data[2], data[1] - 1, data[0]);, data[2] is the year, data[1] the month and data[0] the day, so the builder new Date you will be able to compare if the date is "valid".
  • ano == data[2] checks whether the year of value is equal to the year new Date "understood", if different is why the date was readjusted and the user probably put a wrong or random value.
  • dataObjeto.getMonth() === parseInt(data[1]) compares whether the month was the same as received by value.
  • dataObjeto.getDate() === parseInt(data[0]) compares whether the day was the same as received by value.
  • ano > 1900 and ano < 2100 is your range/range allowed, you can change.

In this code if the user adds a date as is 29/02/2015 (is not leap year, so there is no day 29) new Date will generate this date 2015-03-01T03:00:00.000Z (March 1, 2015), so the date entered by the user is invalid and the validator is on false

Should the field present time and date:

[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy hh:mm}")]

You can use validation to Regex thus:

/^\d{2}\/\d{2}\/\d{4} \d{2}[:]\d{2}$/

And the code should look like this:

date: function (value, element) {
    "use strict";
    var horaData, data, hora, dataObjeto, ano;

    if (this.optional(element) || /^\d{2}\/\d{2}\/\d{4} \d{2}[:]\d{2}$/.test(value)) {
        horaData = value.split(" ");

        data = horaData[0].split("/");
        hora = horaData[1].split(":");

        dataObjeto = new Date(data[2], data[1] - 1, data[0], hora[0], hora[1]);
        ano = dataObjeto.getFullYear();

        return (
            ano === parseInt(data[2]) &&
            dataObjeto.getMinutes() === parseInt(hora[1]) &&
            dataObjeto.getHours() === parseInt(hora[0]) &&
            dataObjeto.getMonth() === parseInt(data[1]) - 1 &&
            dataObjeto.getDate() === parseInt(data[0]) &&
            ano > 1900 && ano < 2100
        );
    }
    return false;
},
  • Hello @Guilherme, thank you for answering, I know the error, is the typing that is in the database, my question is related, how to validate this error, more precisely in View

  • @Rod I edited, now I heeded your question.

  • and when it is a datetime field but it is presented date and time, I think this way will not accept....

  • @rbrock I modified the answer, see if the example helps you.

  • 1

    @Guilhermenascimento almost... I edited there with what I found fitting... please check... here it worked... ;) (Y)

0

  • i own the globalize correctly, and also Culture in the main Web.config(not the areas) and still causes the error I quoted

  • Installed the JS?

  • Yes, that same nuget lib that’s on the link

  • Well, I may be talking nonsense, but the error does not refer to the conversion when trying to write to the database? The table field would not be in the format yyyy/mm/dd???

  • @Gustavoadolfo I think that’s right. In theory it’s something in the format just at the time of recording.

  • @I think the same thing for the error message. Something similar has happened to me and I’ve been looking for trouble where it didn’t exist, until I realized the detail... But I don’t know if this is the case here.

  • 1

    @Gustavoadolfo He made the configuration based on two answers of mine. In theory it should already be working.

  • Hello @Ciganomorrisonmendez If the resolution is in two answers you have already written, so this would not make the current question a duplicate?

  • @Guilhermenascimento More or less. I believe that the problem is not described in any of them, judging by what has been put here so far. I have little time to help now.

Show 4 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.