Era giapponese, festività e date di chiusura nelle applicazioni aziendali — progettazione resiliente ai cambi di era, JapaneseCalendar e calcolo dei giorni lavorativi nella pratica
· Go Komura · C#, .NET, Era giapponese (wareki), Festività, Data di chiusura, Gestione di data e ora, Applicazioni aziendali, Sviluppo Windows, Consulenza tecnica
«La data sul documento deve essere in era giapponese.» «Il pagamento è dovuto con chiusura il giorno 20, saldato entro la fine del mese successivo, oppure il giorno lavorativo precedente se quella data cade in un giorno festivo.» «I totali devono essere aggregati per esercizio fiscale.» Le applicazioni aziendali in Giappone includono di serie requisiti sulle date che non hanno senso in nessun’altra parte del mondo. E questo territorio nasconde un tipo di trappola diverso dalla gestione ordinaria di data e ora. I nomi di era si moltiplicano a ogni transizione, le festività si spostano a ogni modifica legislativa e la «fine del mese» ha una lunghezza diversa a seconda del mese. In altre parole, tutto questo rientra tra le «specifiche che cambiano in seguito».
La volta scorsa, in «Data, ora e fusi orari nelle applicazioni aziendali», abbiamo definito il principio dell’archiviazione in UTC e la gestione dei fusi orari. Questa volta, come seguito, affrontiamo i tre grandi requisiti tipicamente giapponesi: l’era giapponese, le festività e le date di chiusura. Vedremo la progettazione resiliente ai cambi di era, i motivi per cui le festività non vanno mai codificate in modo fisso e come conservarle come dati, e il calcolo delle date di chiusura tenendo conto dell’arrotondamento di AddMonths — il tutto con esempi di codice e tabelle decisionali.
1. Prima di tutto, la conclusione
- L’elaborazione interna e l’archiviazione restano nel calendario gregoriano; l’era giapponese esiste solo al momento della visualizzazione. Archiviare stringhe in era giapponese comporta una tripla penalità: impossibilità di ordinamento, mescolanza di notazioni dopo un cambio di era e rischio che si insinuino date non valide.
- Delegate la conversione dell’era a
JapaneseCalendarinvece che a una tabella di corrispondenza fatta in casa. Le definizioni di era sono fornite dal sistema operativo, quindi un aggiornamento della piattaforma è sufficiente per seguire un cambio di era.1 A restare indietro sono solo le stringhe codificate in modo fisso come «Heisei» o «Reiwa» rimaste nell’applicazione. - Le festività non possono essere determinate con una formula. Gli equinozi di primavera e d’autunno vengono fissati l’anno precedente, e le festività stesse possono essere spostate da una modifica legislativa ordinaria o da una legge di misure speciali.2 Progettate il sistema attorno a una tabella anagrafica delle festività più un processo di aggiornamento, e come fonte dati potete usare il CSV delle festività pubblicato dal Cabinet Office giapponese.
- «Fine mese», «giorno lavorativo» ed «esercizio fiscale» devono essere definiti nelle specifiche prima ancora che nel codice. In particolare
AddMonthsarrotonda automaticamente la fine del mese, quindi il calcolo delle date di chiusura deve sempre partire da una data di riferimento fissa.3
Ecco prima un riepilogo di come archiviare ciascun tipo di dato.
| Dato | Modalità di archiviazione | Momento della conversione/valutazione |
|---|---|---|
| La data stessa (data d’ordine, scadenza di pagamento) | DateOnly / DateTime in gregoriano (colonna date nel DB) |
— |
| Notazione in era giapponese (documenti, schermate) | Non archiviarla | Conversione con JapaneseCalendar solo al momento della visualizzazione/stampa |
| Festività | Tabella anagrafica delle festività (tabella o file di configurazione) | Consultata al momento del calcolo dei giorni lavorativi |
| Chiusure aziendali (ferie estive, anniversario di fondazione) | Tabella delle chiusure separata da quella delle festività | Come sopra (non mescolare con le festività) |
| Data di chiusura / termini di pagamento | Attributo dell’anagrafica del partner commerciale («chiusura il 20, pagamento fine mese successivo») | Calcolata a partire da una data di riferimento al momento della fatturazione |
| Esercizio fiscale | Non archiviarlo (valore derivato) | Calcolato dalla data al momento della visualizzazione/aggregazione |
2. L’era giapponese — che resti solo un fatto di visualizzazione
2.1 Perché unificare internamente sul calendario gregoriano
L’era giapponese è una notazione rivolta alle persone, non una rappresentazione adatta al calcolo. «Heisei 9» e «Reiwa 9» non hanno un ordine definito nel confronto tra stringhe, e qualsiasi calcolo di periodo che attraversi un confine di era finisce comunque per richiedere la conversione al calendario gregoriano. Peggio ancora, il sistema delle ere si arricchisce a ogni transizione, per cui i dati rimasti archiviati in era giapponese accumulano un mix di notazioni vecchie e nuove a ogni cambio. L’insinuarsi di dati non validi come «Showa 64, 10 gennaio» (data mai esistita, poiché dall’8 gennaio si era già in Heisei) è un problema classico dei sistemi che archiviano tal quale l’era inserita così com’è.
C’è un altro vincolo spesso trascurato: JapaneseCalendar di .NET supporta solo le date a partire dall’8 settembre dell’era Meiji 1 (1868).4 Quelle precedenti — ad esempio una vecchia data di nascita proveniente da un registro di famiglia — non possono essere gestite correttamente se restano in notazione di era. Unificando internamente sul calendario gregoriano, tutti questi problemi restano confinati alla sola livello di visualizzazione.
2.2 Visualizzazione e input con JapaneseCalendar
Le uniche classi calendario di .NET in grado di gestire più ere sono JapaneseCalendar (e JapaneseLunisolarCalendar), e lo specificatore di formato g corrisponde al nome dell’era.1 Ecco il codice minimo per visualizzare una data in era giapponese.
using System.Globalization;
var jaJpWareki = new CultureInfo("ja-JP");
jaJpWareki.DateTimeFormat.Calendar = new JapaneseCalendar();
var date = new DateOnly(2026, 7, 11);
Console.WriteLine(date.ToString("ggy年M月d日", jaJpWareki)); // 令和8年7月11日
Console.WriteLine(date.ToString("ggyy/MM/dd", jaJpWareki)); // 令和08/07/11
Per accettare l’input in era giapponese, è più sicuro progettare un’interfaccia in cui l’utente sceglie l’era da una casella combinata e inserisce anno, mese e giorno come numeri, invece di analizzare una stringa di testo libero. Se è indispensabile accettare testo libero, fissate il formato con ParseExact.
var input = "令和8年7月11日";
var parsed = DateTime.ParseExact(input, "ggy年M月d日", jaJpWareki);
Console.WriteLine(parsed.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)); // 2026-07-11
La notazione del primo anno di un’era richiede attenzione. Negli ambienti in cui sono stati applicati gli aggiornamenti per il supporto delle ere, il primo anno di ciascuna era viene formattato di default come «Reiwa Gan-nen» (元年, letteralmente «anno di fondazione») invece che come numero, ed è disponibile un interruttore di compatibilità — Switch.System.Globalization.FormatJapaneseFirstYearAsANumber — per ripristinare la notazione numerica «Reiwa 1».5 Verificate prima dell’implementazione, come parte delle specifiche, se il formato del documento richiede «Reiwa 1» oppure «Reiwa Gan-nen». Un altro punto: di default, il controllo dell’intervallo di anni di ciascuna era è allentato, quindi un valore inesistente come «Heisei 33» viene accettato e convertito nella data reale corrispondente (Reiwa 3). Se serve una validazione rigorosa che rifiuti questo tipo di valori, potete imporla con Switch.System.Globalization.EnforceJapaneseEraYearRanges.5 Se lasciarlo allentato o renderlo rigoroso dipenderà da quanto sono «sporchi» i dati esistenti, in particolare da come volete trattare un valore come «Heisei 32» stampato o inserito prima del cambio di era.
2.3 Codice resiliente ai cambi di era, e ciò che resta indietro
Ciò che si impara dall’esperienza del cambio di era a Reiwa (2019) è che la piattaforma tiene il passo, ma l’implementazione fatta in casa dell’applicazione no. La definizione dei nomi di era non è codificata in modo fisso in .NET: il meccanismo fa riferimento alle informazioni sull’era mantenute dal sistema operativo, quindi, continuando ad applicare gli aggiornamenti del sistema operativo e di .NET, la conversione e la formattazione di JapaneseCalendar seguono automaticamente la nuova era.1 A restare indietro sono asset lato applicazione come i seguenti:
- Tabelle o rami di conversione dell’era fatti in casa, come
if (year >= 2019) era = "令和"; - Nomi di era scritti direttamente in modelli di documenti, formati di cella Excel o moduli prestampati
- Codice che gestisce con regole proprie un’abbreviazione dell’era su un solo carattere come «R» o «H» (frequente nei formati di interscambio con i sistemi centrali)
- I dati stessi archiviati, ancora in notazione di era giapponese
Nel preventivare un intervento di adeguamento al cambio di era, iniziate passando meccanicamente al setaccio l’intero codice sorgente e i modelli con grep cercando «Showa», «Heisei», «Reiwa» e «Gan-nen». Le applicazioni aziendali in funzione fin dall’epoca di VB6 o Access contengono quasi certamente da qualche parte una tabella di conversione fatta in casa, per cui questo tema viene spesso affrontato insieme alla decisione di sopravvivenza descritta in «Prolungare la vita di un’applicazione aziendale VB6/Access, o migrarla».
2.4 Un’insidia nascosta: le impostazioni internazionali di Windows
Un’altra trappola facilmente trascurata. Nelle impostazioni internazionali di Windows, l’utente può cambiare il tipo di calendario del sistema operativo in era giapponese. Poiché CultureInfo.CurrentCulture riflette di default la modifica dell’impostazione dell’utente (un «override utente»),6 su una macchina con questa impostazione, un DateTime.ToString() con formato predefinito della cultura inizia improvvisamente a restituire stringhe in era giapponese come «令和08/07/11». Se il codice scrive date in log, CSV o database usando il ToString() predefinito della cultura, allora solo su quella macchina l’era giapponese si infiltra nei dati archiviati, mandando in crash il parsing a valle.
Il rimedio riporta alla stessa conclusione dell’articolo precedente: qualsiasi stringa di data che attraversi un confine — archiviazione, comunicazione, log — deve sempre essere scritta con CultureInfo.InvariantCulture e un formato esplicito. Il formato predefinito della cultura è riservato alla sola visualizzazione a schermo. Per una visione più ampia dell’impatto della cultura sulla visualizzazione, vedere anche «Localizzazione delle applicazioni WinForms/WPF».
3. Le festività — perché non vanno mai codificate in modo fisso, e come gestire una tabella anagrafica
3.1 Le festività «cambiano»
Non scrivete mai il rilevamento delle festività come uno switch (mese, giorno). Le festività sono definite dalla Legge sulle festività nazionali, e sono cambiate ripetutamente per modifiche legislative e prassi operative.2 Solo con gli esempi recenti:
| Anno | Modifica |
|---|---|
| 2016 | Viene istituito il Giorno della montagna (11 agosto) |
| 2019 | In seguito al cambio di era, il compleanno dell’imperatore si sposta dal 23 dicembre al 23 febbraio. Nel 2019 non c’è stato alcun compleanno dell’imperatore |
| 2019 | In base a un regime speciale legato alla successione imperiale, il 1° maggio (giorno dell’intronizzazione) e altre date diventano festività straordinarie |
| 2020 | Il Giorno dello sport e della salute viene rinominato Giorno dello sport |
| 2020-2021 | In base a una legge di misure speciali legata alle Olimpiadi, il Giorno del mare, il Giorno dello sport e il Giorno della montagna si spostano solo per quegli anni |
Inoltre, il Giorno dell’equinozio di primavera e quello dell’equinozio d’autunno non hanno semplicemente alcuna data scritta nella legge. Vengono fissati e annunciati l’anno precedente sulla base di calcoli astronomici, quindi l’unico modo affidabile per conoscere un futuro equinozio è attendere l’annuncio ufficiale.2 Una formula di calcolo che presuppone che «le festività sono le stesse ogni anno» è, in linea di principio, irrealizzabile.
3.2 Tabella decisionale per le fonti dati e le modalità di archiviazione
Progettate la determinazione delle festività come «dati più un processo di aggiornamento». Ecco un confronto delle principali opzioni.
| Approccio | Contenuto | Casi adatti | Avvertenze |
|---|---|---|---|
| Tabella anagrafica delle festività (gestione propria) | Tabella con data e nome, aggiornata tramite una schermata di amministrazione | Sistemi aziendali in generale che vogliono gestirla insieme alle chiusure aziendali | Integrare l’aggiornamento nel processo operativo (trasformare la verifica annuale in un promemoria a calendario) |
| Importazione del CSV del Cabinet Office | Importare il CSV delle festività pubblicato dal Cabinet Office per aggiornare la tabella | Quando si desidera una fonte primaria autorevole per gli aggiornamenti della tabella (consigliato) | Contiene solo il periodo già pubblicato. Attenzione alla codifica dei caratteri |
| Libreria delle festività (NuGet, ecc.) | Determinazione tramite logica di calcolo più dati inclusi | Usi su piccola scala, come strumenti interni che non possono sostenere un processo di aggiornamento | Le future modifiche legislative dipendono dall’aggiornamento della libreria. Occorre verificare le regole incluse |
| Codifica fissa | Date scritte direttamente nel codice sorgente | Nessuno | Ogni modifica legislativa impone una ridistribuzione a tutti i client |
Come fonte primaria si può usare il CSV delle date e dei nomi delle festività da Showa 30 (1955) fino all’anno successivo, pubblicato dal Cabinet Office nella sua pagina «Festività nazionali».2 Ci sono due precauzioni pratiche in fase di importazione: (1) poiché viene pubblicato solo il periodo già confermato, decidete come parte delle specifiche il comportamento da adottare quando viene richiesta una festività a due o più anni di distanza (restituire un errore, oppure riempire con un valore provvisorio basato sulla legge e un flag «provvisorio»); e (2) la codifica dei caratteri di questo CSV appartiene alla famiglia Shift_JIS, quindi occorre specificare esplicitamente la codifica in lettura, come descritto in «Il CSV non è semplicemente «testo puro»».
3.3 Festività sostitutiva, festività nazionale e calcolo dei giorni lavorativi
Oltre all’elenco delle date, la legge sulle festività definisce due regole derivate: la festività sostitutiva (quando una festività cade di domenica, il giorno successivo più vicino che non sia a sua volta festivo diventa non lavorativo) e la festività nazionale (un giorno feriale incastrato tra due festività diventa non lavorativo).2 Il CSV del Cabinet Office le include anch’esse come righe, quindi con l’approccio di importazione CSV basta consultare la tabella anagrafica. Anche completando questa logica autonomamente, essa resta relativamente stabile poiché deriva dalla legge.
Scrivete il calcolo dei giorni lavorativi con tre condizioni: non essere sabato o domenica, non essere presente nella tabella anagrafica delle festività, non essere presente nella tabella delle chiusure aziendali.
public sealed class BusinessDayCalendar
{
private readonly HashSet<DateOnly> _publicHolidays; // Anagrafica giorni festivi (incluse le festività sostitutive)
private readonly HashSet<DateOnly> _companyHolidays; // Anagrafica giorni di chiusura aziendale
public BusinessDayCalendar(IEnumerable<DateOnly> publicHolidays,
IEnumerable<DateOnly> companyHolidays)
{
_publicHolidays = [.. publicHolidays];
_companyHolidays = [.. companyHolidays];
}
public bool IsBusinessDay(DateOnly d) =>
d.DayOfWeek is not (DayOfWeek.Saturday or DayOfWeek.Sunday)
&& !_publicHolidays.Contains(d)
&& !_companyHolidays.Contains(d);
// Se la scadenza cade in un giorno festivo, la si riporta al giorno lavorativo precedente. Se rimandarla in avanti dipende dalle condizioni contrattuali
public DateOnly ToPreviousBusinessDay(DateOnly d)
{
while (!IsBusinessDay(d)) d = d.AddDays(-1);
return d;
}
}
Tenere le festività e le chiusure aziendali in tabelle separate è una scelta deliberata. «La scadenza di un bonifico bancario guarda solo alle festività nazionali (la nostra chiusura estiva non conta)», «la data di spedizione guarda entrambe» — l’insieme di giorni non lavorativi da considerare dipende dal caso d’uso. Se le mescolate in un’unica tabella, separarle in seguito diventa un lavoro di archeologia sui dati già archiviati.
4. Data di chiusura, termini di pagamento ed esercizio fiscale — gestire correttamente la «fine mese» nel calcolo
4.1 Il comportamento di arrotondamento di AddMonths
La prima trappola nel calcolo delle date di chiusura è AddMonths. DateTime.AddMonths / DateOnly.AddMonths arrotondano all’ultimo giorno del mese risultante quando il calcolo ingenuo darebbe un giorno che non esiste in quel mese.3
var jan31 = new DateOnly(2026, 1, 31);
var feb = jan31.AddMonths(1); // 2026-02-28 ── arrotondato a fine mese (corretto)
var mar = feb.AddMonths(1); // 2026-03-28 ── quello che doveva essere "fine mese" diventa silenziosamente il 28
L’arrotondamento in sé è specificato correttamente, ma concatenare un altro AddMonths su un risultato già arrotondato fa perdere l’intento di «fine mese». Questo si manifesta nella pratica quando un calendario di fatturazione mensile viene costruito come «data dell’ultima esecuzione più un mese»: non appena si attraversa febbraio, il calcolo inizia a slittare permanentemente verso il giorno 28 di ogni mese. Ci sono due contromisure:
- Per le date ripetute, calcolare sempre a partire da la definizione del punto di riferimento («fine di ogni mese», «il giorno 20 di ogni mese»), non dal risultato precedente
- Derivare la «fine mese» da
DateTime.DaysInMonth(y, m)invece che da un valore letterale di data
4.2 Implementazione di «chiusura il 20, pagamento a fine del mese successivo»
La data di chiusura e i termini di pagamento sono attributi propri di ciascun partner commerciale. Codificare «chiusura il 20, pagamento a fine del mese successivo» dà questo risultato:
public static class PaymentTerms
{
// Data operazione → data di chiusura (esempio: chiusura il giorno 20 di ogni mese)
public static DateOnly GetClosingDate(DateOnly tradeDate, int closingDay)
{
var dayInMonth = Math.Min(closingDay, DateTime.DaysInMonth(tradeDate.Year, tradeDate.Month));
var closing = new DateOnly(tradeDate.Year, tradeDate.Month, dayInMonth);
return tradeDate <= closing ? closing : closing.AddMonths(1);
// Nota: closingDay=31 (chiusura di fine mese) diventa correttamente la fine del mese successivo grazie all'arrotondamento di AddMonths
}
// Data di chiusura → data di scadenza del pagamento (esempio: pagamento a fine mese successivo). Verificare le specifiche di adeguamento festivi (anticipo/posticipo) prima di applicarle
public static DateOnly GetPaymentDueDate(DateOnly closingDate, BusinessDayCalendar calendar)
{
var nextMonth = closingDate.AddMonths(1);
var endOfMonth = new DateOnly(nextMonth.Year, nextMonth.Month,
DateTime.DaysInMonth(nextMonth.Year, nextMonth.Month));
return calendar.ToPreviousBusinessDay(endOfMonth); // Per i contratti che usano la regola "se festivo, riportare al giorno lavorativo precedente"
}
}
Più importante del codice è fissare in anticipo le specifiche. In una «chiusura a fine mese», la fine mese si conta in giorni di calendario o in giorni lavorativi? Se la scadenza cade di festivo, si anticipa o si posticipa (chi paga tende ad anticipare, chi riceve tende a posticipare la data di incasso prevista — la prassi varia a seconda del punto di vista)? Come si interpreta a febbraio un contratto con chiusura tra il 29 e il 31? Finché questi punti non sono documentati, il codice di chi lo implementa diventa tal quale «una specifica che nessuno ha mai concordato». La maggior parte dei bug relativi alle date di chiusura, se indagati, non risale a un errore di codice, ma all’assenza di una specifica.
4.3 Esercizio fiscale e trimestre
In Giappone, l’«esercizio fiscale» di un’applicazione aziendale inizia quasi sempre ad aprile. Non archiviatelo: trattatelo come un valore derivato dalla data.
public static int GetFiscalYear(DateOnly d) => d.Month >= 4 ? d.Year : d.Year - 1;
// 2026-03-31 → anno fiscale 2025, 2026-04-01 → anno fiscale 2026
public static int GetFiscalQuarter(DateOnly d) => ((d.Month + 8) % 12) / 3 + 1;
// apr-giu → Q1, lug-set → Q2, ott-dic → Q3, gen-mar → Q4
Fate attenzione a non archiviare in modo ridondante l’esercizio fiscale nel database senza necessità. Conservare in una colonna separata un valore sempre derivabile dalla data crea il rischio che, correggendo una data e dimenticando l’aggiornamento, si ottengano dati in cui la data e l’esercizio fiscale non coincidono più. Se per motivi di prestazioni di aggregazione è indispensabile conservarlo, fatene una colonna calcolata (generata) e vietate la scrittura diretta dall’applicazione.
4.4 Test — anticipare i bug che si manifestano «solo in quel giorno»
I bug legati a era, festività e date di chiusura si manifestano solo in date specifiche. Basandosi sull’iniezione dell’ora corrente tramite TimeProvider presentata nell’articolo precedente (capitolo 7 di «Data, ora e fusi orari nelle applicazioni aziendali»), ecco le cinque date da testare come minimo in questo ambito:
- Confini di cambio era: visualizzazione e conversione inversa di un input in era giapponese intorno al 1989-01-07/08 (Showa → Heisei) e al 2019-04-30/05-01 (Heisei → Reiwa)
- Primo anno di un’era: verifica della notazione «Reiwa Gan-nen» sui documenti (paragrafo 2.2)
- Anni bisestili: calcoli di chiusura e scadenza di pagamento che comprendono il 29 febbraio (2024, 2028)
- Concatenazione di fine mese: generazione di dodici mesi di date di chiusura a partire dal 31 gennaio, verificando che la fine mese venga preservata (paragrafo 4.1)
- Confini di esercizio fiscale: determinazione dell’esercizio fiscale e del trimestre per il 31 marzo e il 1° aprile
Inoltre, in fase di revisione del codice, i seguenti pattern possono essere individuati meccanicamente con grep.
| Codice trovato, da sospettare | Cosa può succedere | Come correggerlo |
|---|---|---|
Valori letterali di era come "平成" o "令和" |
Resta indietro al prossimo cambio di era | Passare a JapaneseCalendar più il formato g (paragrafo 2.3) |
Date festive letterali (come 5, 3) |
Determinazione errata dopo una modifica legislativa o una legge di misure speciali | Passare alla consultazione della tabella anagrafica delle festività (paragrafo 3.2) |
Percorso di salvataggio/output che usa ToString() senza argomenti |
L’era giapponese si infiltra nei dati archiviati su una macchina impostata sulla visualizzazione in era | InvariantCulture più formato esplicito (paragrafo 2.4) |
Ripetizione di dataPrecedente.AddMonths(1) |
La fine mese continua a slittare dopo aver attraversato febbraio | Calcolare ogni volta a partire da una data di riferimento (paragrafo 4.1) |
new DateTime(y, m, 31) |
Genera un’eccezione per i mesi con 30 giorni o meno | Derivarla da DateTime.DaysInMonth |
5. Conclusione
Era giapponese, festività e date di chiusura hanno in comune il fatto di trattare con «specifiche che cambiano in seguito». Per questo il principio di progettazione è lo stesso in tutti e tre i casi: non scrivere nel codice ciò che può cambiare, ma isolarlo nei dati e in uno strato di conversione. Unificate l’elaborazione interna e l’archiviazione sul calendario gregoriano, trattando l’era giapponese come una conversione riservata alla sola visualizzazione; mantenete le festività in una tabella anagrafica con un processo di aggiornamento; documentate «fine mese», «giorno lavorativo» e «adeguamento della scadenza in caso di festività» come specifiche contrattuali prima di calcolarle a partire da una data di riferimento. Fatto questo, il prossimo cambio di era e la prossima modifica della legge sulle festività diventano, per la vostra applicazione, eventi risolvibili con un semplice «aggiornamento della tabella anagrafica» e l’«applicazione dell’aggiornamento del sistema operativo».
Ci occupiamo della progettazione e implementazione della gestione delle date relative a documenti e fatturazione, del censimento e della rimodellazione dei nomi di era e delle festività codificati in modo fisso in applicazioni esistenti, e di revisioni del design che includono la definizione delle specifiche delle date di chiusura. Possiamo aiutarvi anche a partire dalla fase in cui non sapete ancora quanti punti del vostro codice richiedano un adeguamento al cambio di era.
Articoli correlati
- Data, ora e fusi orari nelle applicazioni aziendali — dalle insidie di DateTime al principio dell’archiviazione in UTC e alla progettazione dei test
- Il CSV non è semplicemente «testo puro» — la pratica del CSV nelle applicazioni aziendali C# (codifica dei caratteri, compatibilità con Excel, contromisure contro l’injection)
- Localizzazione delle applicazioni WinForms/WPF — resx, assembly satellite e cambio di cultura nella pratica
- Prolungare la vita di un’applicazione aziendale VB6/Access, o migrarla — una tabella decisionale tra mantenere, avvolgere e sostituire
- Come generare l’output dei documenti Excel - COM / Open XML / modelli
Aree di consulenza correlate
合同会社小村ソフト (KomuraSoft LLC) si occupa della progettazione e implementazione della gestione delle date per applicazioni aziendali coerenti con le prassi commerciali giapponesi (documenti in era giapponese, calcolo dei giorni lavorativi, gestione delle date di chiusura), oltre al censimento e alla rimodellazione della gestione dei cambi di era e delle festività nelle applicazioni esistenti.
- Sviluppo di applicazioni Windows
- Modifica e manutenzione di software Windows esistente
- Consulenza tecnica e revisione del design
- Contatti
Riferimenti
-
Microsoft Learn, Work with eras - .NET. Sul fatto che JapaneseCalendar e JapaneseLunisolarCalendar siano le uniche classi calendario a riconoscere più ere, sulla formattazione dell’era tramite lo specificatore di formato «g», e sul fatto che le informazioni sull’era siano fornite dalla piattaforma anziché dipendere da una codifica fissa nell’applicazione. ↩ ↩2 ↩3
-
Cabinet Office del Giappone, «Sulle festività nazionali». Sull’elenco delle festività secondo la Legge sulle festività nazionali, sul fatto che gli equinozi di primavera e d’autunno vengano fissati e annunciati l’anno precedente, sulle disposizioni relative alla festività sostitutiva e alla festività nazionale, e sulla disponibilità di un CSV di date e nomi delle festività da Showa 30 fino all’anno successivo. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, DateTime.AddMonths(Int32) Method. Sul fatto che, quando il giorno risultante supera il numero di giorni del mese risultante, il risultato venga adeguato all’ultimo giorno di quel mese (ad esempio, il 31 gennaio più un mese diventa il 28/29 febbraio). ↩ ↩2
-
Microsoft Learn, JapaneseCalendar Class. Sull’intervallo di date supportato da JapaneseCalendar — a partire dall’8 settembre dell’era Meiji 1 (1868 d.C.) — e sulla gestione delle ere. ↩
-
Microsoft Learn, Work with calendars - .NET. Sul comportamento predefinito di formattare il primo anno di un’era come «Gan-nen», sull’interruttore Switch.System.Globalization.FormatJapaneseFirstYearAsANumber che ripristina la notazione numerica, e sul fatto che il controllo dell’intervallo di anni di un’era è allentato di default ma può essere reso rigoroso con Switch.System.Globalization.EnforceJapaneseEraYearRanges. ↩ ↩2
-
Microsoft Learn, CultureInfo.CurrentCulture Property. Sul fatto che CurrentCulture rifletta di default le modifiche alle impostazioni internazionali di un utente Windows (un override utente), e che la formattazione predefinita dipenda da questa cultura. ↩
Articoli correlati
Articoli recenti con gli stessi tag per approfondire argomenti vicini.
Icone nella system tray e notifiche toast nelle app Windows — le insidie di NotifyIcon e come scegliere l'AppNotification giusta
Una guida pratica per mantenere un'applicazione Windows aziendale residente nella system tray (area di notifica) e avvisare l'utente tram...
Fino a quando funzioneranno le applicazioni VB6? — Lo stato del supporto al runtime e un percorso pratico verso la migrazione a .NET
Fino a quando continueranno a funzionare le applicazioni VB6? Questo articolo chiarisce l'asimmetria tra la politica di supporto del runt...
Internazionalizzazione delle app WinForms/WPF — la pratica di resx, satellite assembly e cambio cultura
Analizziamo dal punto di vista pratico l'internazionalizzazione delle applicazioni desktop Windows: la differenza tra CurrentCulture e Cu...
Il CSV non è "solo testo" ── La gestione pratica dei file CSV nelle applicazioni aziendali C# (codifica dei caratteri, compatibilità con Excel, protezione dalle injection)
Analizziamo, dal punto di vista pratico, i tipici errori negli scambi CSV delle applicazioni aziendali──il parsing fatto in casa con Spli...
Non racchiudere HttpClient in un using ── guida pratica alla comunicazione HTTP nelle app aziendali C# (pattern di creazione, timeout, retry)
Creare un nuovo HttpClient con using a ogni richiesta esaurisce i socket, mentre renderlo static non segue i cambi di DNS: analizziamo il...
Argomenti correlati
Queste pagine collocano l’argomento in un contesto più ampio di servizi e decisioni.
Argomenti tecnici Windows
Portale su sviluppo Windows, analisi dei problemi e valorizzazione delle risorse esistenti.
Servizi collegati all’argomento
L’articolo è direttamente collegato ai servizi seguenti.
Sviluppo di applicazioni Windows
Implementare requisiti aziendali specifici del Giappone, come la visualizzazione delle date in era giapponese sui documenti, il calcolo dei giorni lavorativi e la gestione delle date di chiusura, rientra nel nucleo della consulenza per lo sviluppo di applicazioni aziendali Windows.
Manutenzione e modernizzazione del software Windows
Censire i nomi di era e le festività codificati in modo fisso in un'applicazione esistente e rimodellarli affinché resistano al prossimo cambio di era o a una modifica legislativa rientra nella modifica e manutenzione di software Windows esistente.
Consulenza tecnica e revisione del progetto
Stabilire fino a che punto formalizzare e gestire tramite dati concetti come «fine mese», «giorno lavorativo» ed «esercizio fiscale» è consulenza tecnica che comporta una revisione del design.
Domande frequenti
Domande che ricorrono nelle consulenze sull’argomento dell’articolo.
- È sbagliato salvare le date direttamente in formato era giapponese nel database?
- Lo sconsigliamo, per quattro motivi. Primo, stringhe di era come «Heisei 9» e «Reiwa 9» perdono ogni ordine coerente nel confronto tra stringhe non appena si attraversa un confine di era, rendendo impossibili l'ordinamento e le ricerche per intervallo. Secondo, nel momento in cui arriva il prossimo cambio di era, le notazioni vecchie e nuove finiscono mescolate nei dati già salvati. Terzo, si insinuano facilmente dati corrotti con date mai esistite, come «Showa 64, 10 gennaio» (quel giorno era già Heisei 1, poiché l'era era cambiata l'8 gennaio), diventando una bomba a orologeria per il parsing. Quarto, JapaneseCalendar di .NET supporta solo le date a partire dall'8 settembre dell'era Meiji 1 (1868); quelle precedenti — ad esempio una vecchia data di nascita proveniente da un registro di famiglia — non possono essere gestite correttamente se mantenute in notazione di era. La regola è unificare l'elaborazione interna e l'archiviazione sul calendario gregoriano, convertendo in era giapponese solo al momento della visualizzazione o della stampa.
- Come dovrebbe prepararsi un'applicazione al prossimo cambio di era?
- La definizione dei nomi di era non è codificata in modo fisso in .NET stesso: il meccanismo fa riferimento alle informazioni sull'era fornite dal sistema operativo, quindi è sufficiente continuare ad applicare gli aggiornamenti del sistema operativo e di .NET perché la capacità di «visualizzare la nuova era» segua automaticamente. Anche durante la transizione a Reiwa, il grosso della risposta è consistito semplicemente nell'applicare gli aggiornamenti della piattaforma. Il vero problema riguarda il codice e i dati lato applicazione: rami condizionali che codificano in modo fisso «Heisei» o «Reiwa» come stringhe, funzioni di conversione fatte in casa con una propria tabella di corrispondenza era-anno gregoriano, nomi di era scritti direttamente nei modelli dei documenti, o campi «Reiwa __» su moduli prestampati non seguono automaticamente. Quattro misure pratiche sono ragionevoli: (1) unificare internamente e in fase di archiviazione sul calendario gregoriano, in modo che l'era giapponese sia solo di visualizzazione; (2) abbandonare la logica di conversione dell'era fatta in casa a favore di JapaneseCalendar; (3) analizzare l'intero codice sorgente con grep cercando «Showa», «Heisei» e «Reiwa» per farne un censimento; e (4) predisporre test che simulino un ipotetico futuro cambio di era.
- Le festività non possono essere determinate con una formula di calcolo? Perché è necessario conservarle come dati?
- Una formula completa è, in linea di principio, impossibile da costruire, per tre motivi. Primo, il Giorno dell'equinozio di primavera e quello dell'equinozio d'autunno vengono fissati l'anno precedente tramite decisione del Consiglio dei ministri basata su calcoli astronomici: non sono scritti nella legge come date fisse. Secondo, le festività vengono aggiunte, spostate o rinominate tramite modifiche legislative: nel 2016 è stato istituito il Giorno della montagna, nel 2019 il compleanno dell'imperatore si è spostato dal 23 dicembre al 23 febbraio in seguito al cambio di era (**nel 2019 non c'è stato alcun compleanno dell'imperatore**), e il Giorno dello sport e della salute è stato rinominato Giorno dello sport. Terzo, nel 2020 e nel 2021 una legge di misure speciali legata alle Olimpiadi ha spostato il Giorno del mare, il Giorno dello sport e il Giorno della montagna **solo per quegli anni**, dimostrando che anche una regola come «sempre il terzo lunedì» può essere temporaneamente sovrascritta. La progettazione corretta è quindi una «tabella anagrafica delle festività più un processo di aggiornamento», limitando la logica di calcolo a regole ausiliarie come la festività sostitutiva.
- La mia scadenza di pagamento si è spostata rispetto alla fine del mese dopo aver usato AddMonths(1). Perché?
- Perché DateTime.AddMonths è specificato per arrotondare all'ultimo giorno del mese risultante quando il calcolo ingenuo darebbe un giorno che non esiste in quel mese. Applicare AddMonths(1) al 31 gennaio dà il 28 febbraio (o il 29 negli anni bisestili) — questo comportamento in sé è corretto. Ma se poi si riporta questo risultato arrotondato in un nuovo AddMonths, applicare AddMonths(1) al 28 febbraio dà il 28 marzo, e da lì lo slittamento prosegue indefinitamente: quella che doveva essere la «fine del mese» si trasforma silenziosamente, e in modo permanente, nel «giorno 28». Il rimedio ha due componenti: per i calcoli ripetuti, calcolare sempre a partire da un punto di riferimento fisso (la data del contratto, o la definizione di «fine di ogni mese») invece di sommare al risultato precedente, e derivare la «fine mese» da DateTime.DaysInMonth invece che da un valore letterale di data.
Profilo dell’autore
Pagina di presentazione dell’autore dell’articolo.
Go Komura
Rappresentante di KomuraSoft LLC
Specializzato nello sviluppo di software Windows, nella consulenza tecnica e nell’analisi dei malfunzionamenti, soprattutto nei progetti con sistemi esistenti e guasti difficili da riprodurre.
Link pubblici