Calcolo degli intervalli temporali con Luxon Business Day
Tempo di lettura: 4 minuti

Poco fa, nel maggio del 2021, ho scritto di Lo status di Luxon come erede apparente di Moment.js poiché il successivo è entrato in modalità di manutenzione. Da allora, i creatori di plugin per Moment.js si sono affrettati a migrare le loro librerie a Luxon, poiché sempre più organizzazioni lo adottano come loro di fatto Libreria di date JS.

Uno di questi plugin è Luxon giorni lavorativi. Come suggerisce il nome, è una libreria per il calcolo e la manipolazione dei giorni lavorativi che si basa su di essa Momento di giorni lavorativi precursore.

In questo tutorial, utilizzeremo Luxon Business Days per accedere a una serie di prezzi azionari giornalieri senza dover ripetere da soli ogni elemento per trovare un giorno specifico.

Il compito spiegato

Supponiamo di avere un oggetto che memorizza una serie temporale giornaliera e i relativi prezzi delle azioni:

const DAY_TIMESERIES = {
  close: [
    174.92, 
    172, 
    172.17, 
    172.19, 
    175.08, 
    175.53, 
    172.19, 
    173.07, 
    173.07, 
    169.8, 
    166.23, 
    164.51, 
    162.41, 
    161.62, 
    159.78, 
    159.69, 
    159.22, 
    170.33, 
    174.78, 
    174.61, 
    175.84, 
    172.9, 
    172.39, 
    171.66, 
    174.83, 
    176.28, 
    172.12, 
    168.64, 
    168.88, 
    172.79, 
    172.55, 
    168.88, 
    167.3, 
    167.3, 
    169.32, 
    170.07, 
    162.74
  ],
  timestamps: [
    "2022-01-05T00:00:00",
    "2022-01-06T00:00:00",
    "2022-01-07T00:00:00",
    "2022-01-10T00:00:00",
    "2022-01-11T00:00:00",
    "2022-01-12T00:00:00",
    "2022-01-13T00:00:00",
    "2022-01-14T00:00:00",
    "2022-01-17T00:00:00",
    "2022-01-18T00:00:00",
    "2022-01-19T00:00:00",
    "2022-01-20T00:00:00",
    "2022-01-21T00:00:00",
    "2022-01-24T00:00:00",
    "2022-01-25T00:00:00",
    "2022-01-26T00:00:00",
    "2022-01-27T00:00:00",
    "2022-01-28T00:00:00",
    "2022-01-31T00:00:00",
    "2022-02-01T00:00:00",
    "2022-02-02T00:00:00",
    "2022-02-03T00:00:00",
    "2022-02-04T00:00:00",
    "2022-02-07T00:00:00",
    "2022-02-08T00:00:00",
    "2022-02-09T00:00:00",
    "2022-02-10T00:00:00",
    "2022-02-11T00:00:00",
    "2022-02-14T00:00:00",
    "2022-02-15T00:00:00",
    "2022-02-16T00:00:00",
    "2022-02-17T00:00:00",
    "2022-02-18T00:00:00",
    "2022-02-21T00:00:00",
    "2022-02-22T00:00:00",
    "2022-02-23T00:00:00",
    "2022-02-24T00:00:00"
  ]
};

La bellezza degli array paralleli a Luxon

Per questo tutorial, manterremo breve la lunghezza delle serie temporali e le limiteremo a circa due mesi. In uno scenario reale, le serie temporali potrebbero estendersi indietro di anni, quindi è bene evitare di ripetere sia le timestamp e chiudere matrici. Fortunatamente, non dobbiamo. Per capire perché, immagina che stavamo cercando il prezzo delle azioni 21 febbraio 2022. Per farlo, dovremmo prima trovare quale timestamp l’elemento conteneva la data che stiamo cercando. Da lì, potremmo recuperare il prezzo dal chiudere array usando lo stesso indice di elemento, perché entrambi i timestamp e chiudere sono Array paralleli. Conosciuto anche come Struttura degli array (SoA)si tratta di più array della stessa dimensione in modo tale che il ennesimo l’elemento di ogni array è correlato in modo che all ennesimo gli elementi insieme rappresentano un oggetto o un’entità. Li troverai ovunque nel codice dell’applicazione, ma un esempio di array parallelo sono due array che rappresentano X e y coordinate di n punti.

Quindi, trovare l’indice di un elemento ci punta automaticamente ai dati correlati nell’altro array.

Leggere: Conversione TimeZone con Luxon e JavaScript

Calcolo del numero di giorni tra due date utilizzando Luxon

Una delle cose in cui Luxon è estremamente bravo è calcolare la durata tra le date. In effetti, sarebbero necessarie solo tre righe di codice per trovare il numero di giorni tra il primo timestamp e il 21 febbraio 2022 data obiettivo che stiamo cercando:

const firstClosingPriceDate = DateTime.fromISO(DAY_TIMESERIES.timestamps[0]); //"2022-01-05T00:00:00"
const targetPriceCalcDate = DateTime.fromISO("2022-02-21T00:00:00");

let diffInDays = targetPriceCalcDate.diff(firstClosingPriceDate, 'days').days;  //47

Il diff() il metodo restituisce un oggetto Duration, quindi è necessario accedere a giorni proprietà se vogliamo solo i giorni e nessun altro intervallo, come settimane o mesi.

Calcolo del numero di giorni lavorativi tra due date

Mentre il risultato di cui sopra (47) ha ragione, c’è un problema: i prezzi giornalieri delle azioni vengono forniti solo nei giorni lavorativi! Se osservi attentamente i timestamp, noterai che c’è un intervallo di due giorni ogni cinque giorni. A quanto pare, la libreria Moment Business Days ha il businessDiff() metodo, che salta convenientemente i giorni non lavorativi nei suoi calcoli. Ovviamente, dal momento che stiamo usando Luxon, ha senso solo accoppiarlo con il Luxon giorni lavorativi collegare.

Questo è probabilmente un buon momento per ricordare che il Luxon giorni lavorativi plugin non è un port completo della sua controparte Moment.js. E, come vuole il destino, il metodo businessDiff() è vistosamente assente dalla documentazione, dall’oggetto globale dello spazio dei nomi DateTime e dal codice sorgente. Questo significa che il nostro piano è morto nell’acqua? Lontano da esso. Possiamo trasferire Moment.js businessDiff() metodo al nostro progetto. Certo, non funzionerà subito con Luxon, ma grazie a Luxon’s Per gli utenti del momento pagina, possiamo facilmente sostituire gli equivalenti Luxon con le invocazioni del metodo Moment. Ecco la nuovissima compatibilità Luxon businessDiff() metodo:

DateTime.prototype.businessDiff = function(d2, relative) {
  var d1 = this;
  var positive = d1 >= d2;
  var start = d1 < d2 ? d1 : d2;
  var end = d2 > d1 ? d2 : d1;
  var daysBetween = 0;

  if (start.hasSame(end, 'day')) {
    return daysBetween;
  }

  while (start.startOf('day') < end.startOf('day')) {
    if (start.isBusinessDay()) {
      daysBetween += 1;
    }
    start = start.plus({ days: 1 })
  }

  if (!end.isBusinessDay()) {
    daysBetween -= 1;
  }

  if (relative) {
    return (positive ? daysBetween : -daysBetween);
  }

  return daysBetween;
};

Il businessDiff() metodo ritorna 33che equivale all’indice per recuperare i dati sui prezzi:

let diffInDays = targetPriceCalcDate.businessDiff(firstClosingPriceDate); // 33

document.write(pricesFromTargetPriceCalcDate[diffInDays]); //172.79
document.write(
  DateTime.fromISO(daysFromTargetPriceCalcDate[diffInDays]).toLocaleString(DateTime.DATE_MED)
); //Feb 15, 2022

Leggere: Analisi di date e orari con Luxon

La demo

Nel demo codepen.ioil businessDiff() il metodo viene utilizzato per affettare il chiudere e timestamp matrici al giorno dopo il targetPriceCalcDatein modo da poter cercare il primo giorno in cui il prezzo di chiusura del titolo corrisponde o supera il prezzo target, utilizzando il Array.findIndex() metodo:

const targetPriceAchievedIndex 
  = pricesFromTargetPriceCalcDate.findIndex(price => price >= targetPrice) + 1;

Conclusione

Non sei un fan del loop? Perché non lasciare che qualcun altro gestisca il carico dell’iterazione dell’array per te? Grazie a metodi come diff(), businessDiff(), Trovare()e trovaIndice()puoi dimenticare tutto sui loop e sul codice in un modo più orientato al metodo che è più vicino alla programmazione funzionale rispetto al tuo tipico JavaScript.

Leggi di più Tutorial di programmazione JavaScript e sviluppo web.

Source link

Di Simone Serra

Web Designer Freelancer Realizzazione Siti Web Serra Simone Realizzo siti web, portali ed e-commerce con focus specifici sull’usabilità, l’impatto grafico, una facile gestione e soprattutto in grado di produrre conversioni visitatore-cliente. Elaboro siti internet, seguendo gli standard Web garantendo la massima compatibilità con tutti i devices. Sviluppo e-commerce personalizzati, multilingua, geolocalizzati per potervi mettere nelle migliori condizioni di vendita. Posiziono il tuo sito su Google per dare maggiore visibilità alla tua attività sui motori di ricerca con SEO di base o avanzato.