Italiano

Una guida completa all'uso dell'API Temporal di JavaScript per calcoli di intervalli di tempo precisi e intuitivi, dalla creazione di base di durate all'aritmetica e formattazione avanzate.

JavaScript Temporal Duration: Padroneggiare i Calcoli degli Intervalli di Tempo

L'API Temporal di JavaScript introduce un modo moderno e potente per gestire date, orari e intervalli di tempo. L'oggetto Temporal.Duration rappresenta un lasso di tempo, fornendo un approccio chiaro e intuitivo per eseguire calcoli con intervalli di tempo. Questo articolo approfondisce i dettagli di Temporal.Duration, dimostrando come creare, manipolare e formattare durate per vari casi d'uso.

Cos'è Temporal.Duration?

Temporal.Duration rappresenta un arco di tempo, esprimendolo in termini di anni, mesi, giorni, ore, minuti, secondi e frazioni di secondo (millisecondi, microsecondi, nanosecondi). A differenza degli oggetti Date, che rappresentano un punto specifico nel tempo, Temporal.Duration rappresenta una quantità di tempo. Aderisce al formato di durata ISO 8601 (ad es., P1Y2M10DT2H30M rappresenta 1 anno, 2 mesi, 10 giorni, 2 ore e 30 minuti). L'API Temporal è progettata per essere più intuitiva e meno soggetta a errori rispetto all'oggetto legacy Date.

Creazione di Oggetti Temporal.Duration

Esistono diversi modi per creare oggetti Temporal.Duration:

1. Da un Oggetto Semplice

È possibile creare una durata passando un oggetto con le proprietà desiderate:

const duration = new Temporal.Duration(1, 2, 10, 2, 30, 0, 0, 0);
console.log(duration.toString()); // Output: P1Y2M10DT2H30M

Questo crea una durata di 1 anno, 2 mesi, 10 giorni, 2 ore e 30 minuti. Si noti che gli argomenti corrispondono al seguente ordine: years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds.

2. Da una Stringa ISO 8601

È anche possibile creare una durata da una stringa di durata ISO 8601 utilizzando Temporal.Duration.from():

const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
console.log(duration.toString()); // Output: P1Y2M10DT2H30M

Questo è particolarmente utile quando si ha a che fare con durate memorizzate in formato stringa o ricevute da una fonte esterna.

3. Usando i metodi add() e subtract() con Temporal.Instant, Temporal.ZonedDateTime, ecc.

Quando si aggiunge o si sottrae Temporal.Duration da altri tipi Temporal (come Temporal.Instant o Temporal.ZonedDateTime), viene restituito un Temporal.Duration che rappresenta la differenza tra i due punti nel tempo se poi li si sottrae. Per esempio:

const now = Temporal.Now.zonedDateTimeISO();
const later = now.add({ hours: 5 });
const duration = later.since(now);
console.log(duration.toString()); // Output: PT5H

Accesso ai Componenti della Durata

È possibile accedere ai singoli componenti di un oggetto Temporal.Duration utilizzando le sue proprietà:

const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
console.log(duration.years);      // Output: 1
console.log(duration.months);     // Output: 2
console.log(duration.days);       // Output: 10
console.log(duration.hours);      // Output: 2
console.log(duration.minutes);     // Output: 30
console.log(duration.seconds);     // Output: 0
console.log(duration.milliseconds); // Output: 0
console.log(duration.microseconds); // Output: 0
console.log(duration.nanoseconds);  // Output: 0

Eseguire Calcoli Aritmetici con le Durate

Gli oggetti Temporal.Duration supportano l'addizione e la sottrazione tramite i metodi add() e subtract(). Questi metodi restituiscono un nuovo oggetto Temporal.Duration che rappresenta il risultato dell'operazione.

const duration1 = Temporal.Duration.from("P1Y2M");
const duration2 = Temporal.Duration.from("P3M4D");

const addedDuration = duration1.add(duration2);
console.log(addedDuration.toString()); // Output: P1Y5M4D

const subtractedDuration = duration1.subtract(duration2);
console.log(subtractedDuration.toString()); // Output: P10M26D

È anche possibile concatenare questi metodi per calcoli più complessi:

const duration = Temporal.Duration.from("P1D").add({ hours: 12 }).subtract({ minutes: 30 });
console.log(duration.toString()); // Output: P1DT11H30M

Il metodo negated() restituisce un nuovo oggetto Temporal.Duration con tutti i componenti negati:

const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
const negatedDuration = duration.negated();
console.log(negatedDuration.toString()); // Output: -P1Y2M10DT2H30M

Il metodo abs() restituisce un nuovo oggetto Temporal.Duration con tutti i componenti come valori positivi (valori assoluti):

const duration = Temporal.Duration.from("-P1Y2M10DT2H30M");
const absoluteDuration = duration.abs();
console.log(absoluteDuration.toString()); // Output: P1Y2M10DT2H30M

Il metodo with() permette di creare una nuova istanza di Temporal.Duration con alcune, o tutte, le proprietà cambiate a nuovi valori. Se un valore non è specificato nell'oggetto argomento, verrà utilizzato il valore originale della durata. Per esempio:

const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
const newDuration = duration.with({ years: 2, days: 5 });
console.log(newDuration.toString()); // Output: P2Y2M5DT2H30M

Normalizzazione delle Durate

Le durate possono talvolta essere espresse in una forma non normalizzata (ad es., P1Y12M, che potrebbe essere semplificato in P2Y). Il metodo normalized() tenta di semplificare una durata nella sua forma più compatta. Tuttavia, richiede una data di riferimento per gestire le complessità delle diverse lunghezze dei mesi. Per normalizzare correttamente, avrai bisogno di un'istanza di Temporal.PlainDate, Temporal.ZonedDateTime o Temporal.Instant.

Ad esempio, la normalizzazione di una durata che coinvolge mesi e giorni richiede una data di riferimento:

const duration = Temporal.Duration.from("P1M32D");
const referenceDate = Temporal.PlainDate.from("2024-01-01");
const normalizedDuration = duration.normalized({ relativeTo: referenceDate });
console.log(normalizedDuration.toString()); // Output: P2M1D

In questo esempio, la durata P1M32D è normalizzata rispetto al 1° gennaio 2024, risultando in P2M1D perché gennaio ha 31 giorni.

Se si ha a che fare solo con componenti di tempo (ore, minuti, secondi, ecc.), è possibile normalizzare senza una data di riferimento:

const duration = Temporal.Duration.from("PT25H61M");
const normalizedDuration = duration.normalized({ relativeTo: null }); //o omettere l'argomento relativeTo
console.log(normalizedDuration.toString()); // Output: P1DT2H1M

Confronto tra Durate

È possibile confrontare le durate utilizzando il metodo compare(). Questo metodo restituisce:

const duration1 = Temporal.Duration.from("P1Y");
const duration2 = Temporal.Duration.from("P6M");

const comparisonResult = Temporal.Duration.compare(duration1, duration2);
console.log(comparisonResult); // Output: 1

Esempi Pratici

1. Calcolare il Tempo Rimanente fino a un Evento

Supponiamo di voler calcolare il tempo rimanente fino a un evento specifico. Usando Temporal.Now.zonedDateTimeISO() per ottenere l'ora corrente e sottraendo la data dell'evento. Se la data dell'evento è passata, l'output sarà negativo.

const eventDate = Temporal.ZonedDateTime.from({ timeZone: 'America/Los_Angeles', year: 2024, month: 12, day: 25, hour: 9, minute: 0, second: 0 });
const now = Temporal.Now.zonedDateTimeISO('America/Los_Angeles');

const durationUntilEvent = eventDate.since(now);

console.log(durationUntilEvent.toString()); // Output: es., P262DT14H30M (a seconda della data e ora correnti)

2. Monitorare la Durata delle Attività di un Progetto

Nella gestione dei progetti, è possibile utilizzare Temporal.Duration per monitorare la durata stimata o effettiva delle attività.

const task1EstimatedDuration = Temporal.Duration.from("PT8H"); // 8 ore
const task2EstimatedDuration = Temporal.Duration.from("PT16H"); // 16 ore

const totalEstimatedDuration = task1EstimatedDuration.add(task2EstimatedDuration);
console.log(`Durata totale stimata: ${totalEstimatedDuration.toString()}`); // Output: Durata totale stimata: P1DT

3. Calcolo dell'Età

Anche se il calcolo preciso dell'età richiede di considerare gli anni bisestili e i fusi orari, Temporal.Duration può fornire una stima ragionevole:

const birthDate = Temporal.PlainDate.from("1990-05-15");
const currentDate = Temporal.PlainDate.from("2024-01-20");

const ageDuration = currentDate.since(birthDate, { smallestUnit: 'years' });
console.log(`Età stimata: ${ageDuration.years} anni`); // Output: Età stimata: 33 anni

4. Visualizzare Durate Leggibili dall'Uomo

Spesso è necessario visualizzare le durate in un formato leggibile dall'uomo. Sebbene Temporal.Duration non disponga di funzioni di formattazione integrate, è possibile creare una logica di formattazione personalizzata:

function formatDuration(duration) {
  const parts = [];
  if (duration.years) parts.push(`${duration.years} ${duration.years > 1 ? 'anni' : 'anno'}`);
  if (duration.months) parts.push(`${duration.months} ${duration.months > 1 ? 'mesi' : 'mese'}`);
  if (duration.days) parts.push(`${duration.days} ${duration.days > 1 ? 'giorni' : 'giorno'}`);
  if (duration.hours) parts.push(`${duration.hours} ${duration.hours > 1 ? 'ore' : 'ora'}`);
  if (duration.minutes) parts.push(`${duration.minutes} ${duration.minutes > 1 ? 'minuti' : 'minuto'}`);
  if (duration.seconds) parts.push(`${duration.seconds} ${duration.seconds > 1 ? 'secondi' : 'secondo'}`);

  return parts.join(', ');
}

const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
const formattedDuration = formatDuration(duration);
console.log(formattedDuration); // Output: 1 anno, 2 mesi, 10 giorni, 2 ore, 30 minuti

Utilizzo Avanzato e Considerazioni

1. Gestione dei Fusi Orari

Quando si lavora con intervalli di tempo che attraversano i confini dei fusi orari o le transizioni dell'ora legale, è fondamentale utilizzare Temporal.ZonedDateTime per garantire calcoli accurati. L'uso di Temporal.PlainDate e Temporal.PlainTime eviterà qualsiasi conversione di fuso orario.

2. Unità Più Piccola e Arrotondamento

I metodi `since()` e `until()` accettano spesso opzioni per definire l'unità più piccola per la durata risultante. Ad esempio, calcolando il tempo *fino a* un evento e limitando i risultati ai giorni.

const eventDate = Temporal.PlainDate.from("2024-12-25");
const now = Temporal.PlainDate.from("2024-01-20");

const durationUntilEvent = now.until(eventDate, { smallestUnit: 'days' });

console.log(durationUntilEvent.toString()); //esempio di output PT340D

3. Secondi intercalari

Temporal non tiene conto nativamente dei secondi intercalari. Se si richiede una precisione estrema, sarà necessario gestire i secondi intercalari separatamente.

4. Fusi Orari IANA

L'API Temporal si basa sul database dei fusi orari IANA (Internet Assigned Numbers Authority). Assicurarsi che il proprio ambiente disponga di una versione aggiornata del database IANA per gestire accuratamente le conversioni di fuso orario.

Migliori Pratiche

Errori Comuni

Casi d'Uso Reali in Culture Diverse

L'API Temporal può essere particolarmente vantaggiosa nelle applicazioni globali in cui le differenze di fuso orario e le sfumature culturali sono significative. Ecco alcuni esempi:

Conclusione

Temporal.Duration offre un modo robusto e intuitivo per lavorare con intervalli di tempo in JavaScript. By understanding its features and best practices, you can confidently perform accurate and reliable duration calculations in your applications. Abbracciare l'API Temporal porta a un codice più pulito e manutenibile e riduce il rischio di errori associati alla gestione legacy di date e orari.

Man mano che approfondisci l'API Temporal, ricorda di consultare la documentazione ufficiale e di sperimentare con diversi scenari per coglierne appieno le capacità. Con il suo design moderno e le sue funzionalità complete, Temporal è destinato a rivoluzionare il modo in cui gestiamo date, orari e durate in JavaScript.