Range of dates typescript

0

I update:

I have several objects with start dates and end dates.

When inserting / modifying an object, the start or end date of the new object can not be between an existing object.

That is: Exists: 06/06/2018 ----- 06/30/2018

The user can enter:

04/06/2018-------05/06/2018
02/02/2018------ hasta menor que fecha Inicio del que existe (05/06/2018)
o Mayores: 
31/06/2018--------

Can not get in:

 04/06/2018-------07/06/2018 El fin ya está comprendido entre el principio y fin existe.

O

07/06/2018---08/06/2018 porque también está comprendido entre el principio y fin del existe.

Code:

  validateParamsDates(url, newConfig) {

    return this.http.get<any>(url).pipe(map(param => {

      let messageError = { message: "", showAlert: false };

      let userStart = newConfig.startdatevalidity;
      let userFinish = newConfig.enddatevalidity;

      param[1]['params'].array.forEach(element => {

        if(userStart > element.startdatevalidity && userFinish > element.enddatevalidity
           || userStart <  element.startdatevalidity && userFinish < element.enddatevalidity
           && userStart > element.enddatevalidity
          ){
            console.log('good');
        }else{
         console.log('=(');
        }

      });

      return messageError  ;

    }));

  }

Is it correct?

    
asked by EduBw 27.06.2018 в 12:07
source

1 answer

2

As you were told, it is common to use moment.js to abstract that layer of logic. However, it can also be resolved by adapting your dates to a format that complies with ISO-8601

var fecha1='01/12/2018',
    fecha2='2018-12-01';
    
console.log('fecha 1 se evalúa como', new Date(fecha1).toISOString().split('T')[0]);
console.log('fecha 2 se evalúa como', new Date(fecha2).toISOString().split('T')[0]);

Why in the first case transposes the month with the day? Well, that's the format in English. And precisely because of that ambivalence is a bad idea to use it in your code.

If you are certain that all your dates have the form dd/MM/YYYY you can transform them by doing a normalization function:

function normalizaFecha(fecha_str) {
   if(/\d{2}\/\d{2}\/\d{4}/.test(fecha_str)) {
     return fecha_str.split('/').reverse().join('-');
   }
   return fecha_str;
}

And with that you can make a comparison of the type:

if(normalizaFecha(Objeto2.inicio) > normalizaFecha(Objeto1.fin)) {
   throw new Error('Fechas se superponen');
}

Edit: If you are using a calendar plugin for the user to choose their date or enter it in a text field and, again, you know it comes in the DD / format MM / YYYY You can use the function that I showed you. Using moment.js you could use:

moment('01/06/2016', 'DD/MM/YYYY')

To instruct you to interpret the date with the Latin format.

In your case you have

param[1]['params'].array.forEach(element => {

    if(userStart > element.startdatevalidity && userFinish > element.enddatevalidity
       || userStart <  element.startdatevalidity && userFinish < element.enddatevalidity
       && userStart > element.enddatevalidity
      ){
        console.log('good');
    }else{
     console.log('=(');
    }

  });

In that code I think there are missing parentheses to isolate the conditions ( it is better to use defensive pages said Eric S. Raymond almost 30 years ago)

I think it's easier to focus on the reverse:

  • If the start date is contained in the range - > error
  • If the end date is contained in the range - > error
  • If the range contains the entered range - > error
  • If the entered range contains the range - > error

The third condition is not necessary to check it because it falls within the first.

Abstracting this to one purpose:

function validaRango(nuevoRango, rangoExistente) {

  let iniNuevo = nuevoRango.startdatevalidity,
      finNuevo = nuevoRango.enddatevalidity,
      iniExistente = rangoExistente.startdatevalidity,
      finExistente = rangoExistente.enddatevalidity;

  if (iniNuevo > iniExistente && iniNuevo < finExistente ) {
    return false; // fecha inicio se superpone
  }

  if (finNuevo > iniExistente && finNuevo < finExistente ) {
    return false; // fecha fin se superpone
  }

  if (iniNuevo < iniExistente &&  finNuevo > finExistente) {
    return false; // nuevo rango contiene al rango ya ocupado
  }
  return true;
}

If your values for startdatevalidity and enddatevalidity you know that they come in DD/MM/YY format then use the auxiliary function that I passed to you:

function normalizaFecha(fecha_str) {
   if(/\d{2}\/\d{2}\/\d{4}/.test(fecha_str)) {
     return fecha_str.split('/').reverse().join('-');
   }
   return fecha_str;
}

function validaRango(nuevoRango, rangoExistente) {

  let iniNuevo = normalizaFecha(nuevoRango.startdatevalidity),
      finNuevo = normalizaFecha(nuevoRango.enddatevalidity),
      iniExistente = normalizaFecha(rangoExistente.startdatevalidity),
      finExistente = normalizaFecha(rangoExistente.enddatevalidity);

  if (iniNuevo > iniExistente && iniNuevo < finExistente ) {
    return false; // fecha inicio se superpone
  }

  if (finNuevo > iniExistente && finNuevo < finExistente ) {
    return false; // fecha fin se superpone
  }

  if (iniNuevo < iniExistente &&  finNuevo > finExistente) {
    return false; // nuevo rango contiene al rango ya ocupado
  }
  return true;
}

And in the loop you use:

param[1]['params'].array.forEach(element => {

    if(validaRango(newConfig, element)) {
      console.log('good');
    }else{
      console.log('=(');
    }
});

Bonus track to use moment.js with Angular / Typescript

recent versions of moment.js come with definition of types if you want to use typescript with all its validations:

# instalas la librería
npm i moment

And in your component of AngularJS you do:

import * as moment from 'moment';

Then you can for example create a function that converts a string with the format DD/MM/YYYY to an object of type moment.Moment

dateToMoment(date_str: string): moment.Moment {
  return moment(date_str, 'DD/MM/YYYY');
}

Either one that receives an object of type moment.Moment and returns it as a string:

momentToString(momentObj: moment.Moment): string {
  return momentObj.format();
}

Actually if you want to go from a string DD/MM/YYYY to a YYYY-MM-DD you do not need to use the type moment.Moment since the function normalizaFecha would be simply:

normalizaFecha(date_str: string): string {
  return moment(date_str, 'DD/MM/YYYY').format();
}

But it serves to illustrate the type of data that Typescript would expect from a moment object.

    
answered by 27.06.2018 в 13:54