Perché non esiste un tipo di dati solo per una data?

4

Una delle prime cose che ho imparato su date e ore in c # (e varie altre lingue) è che una data viene memorizzata come DateTime con il componente orario impostato a mezzanotte. Non c'è differenza tra "1 gen 2017" e "1 gennaio 2017 00: 00: 00.000". Se è necessario visualizzare solo una data, è possibile utilizzare le funzioni di formattazione come ToString per rimuovere la porzione di tempo.

Questo sembra causare molti problemi, alcuni dei quali li elencherò qui:

  1. DateTime occupa più spazio di archiviazione del necessario: 8 byte invece del 3 richiesto per una data semplice.

  2. L'uso di 00:00:00 per "nessuna data" confonde "un valore noto di 0" con "valore sconosciuto". Questo sembra piuttosto noobish, allo stesso modo un nuovo programmatore potrebbe confondere una stringa nulla con una stringa vuota. Null e empty sono diversi, e "no time" e "midnight" sono idee diverse.

  3. Vedi idiomi come questo che appaiono, anche in comparazioni relativamente semplici:

    if (startDate >= myDateTime && myDateTime < endDate.AddDays(1))
    

    o

    if (startDateTime >= myDate && myDate <= endDateTime.Date)
    

    invece di molto più semplice

    if (startDate >= myDate && myDate <= endDate)
    
  4. Quando i componenti di sistema situati in fusi orari diversi si richiamano sui servizi Web e lo schema per tali servizi Web viene generato dai tipi c #, è possibile introdurre un elemento temporale (in modo che la data risultante si verifichi all'inizio del mattina), o il valore della data può effettivamente spostarsi di un giorno (ad esempio la data finale è in realtà il giorno precedente in un momento in tarda serata). Ciò può rendere doloroso trasmettere valori che sono agnostici rispetto al fuso orario, ad es. una data di nascita o una data di scadenza della carta di credito.

SQL Server ha un tipo Date che memorizza solo mese, giorno e anno.

XSD specifica diversi tipi di dati per data, ora e data.

Perché c # non ha questo tipo?

Come lavori intorno ad esso? Ad esempio, è possibile attribuire le proprietà c # in modo che vengano serializzate come Data anziché come DateTime?

    
posta John Wu 27.03.2017 - 21:37
fonte

4 risposte

14

Che cos'è una data?

Diciamo che è mezzogiorno nella tua regione. Guarderai il tuo orologio e vedrai qualcosa come 22/03/2017 12:00. Potresti dire facilmente che questa è la data corrente per tutti gli altri al mondo, giusto?

Beh, non proprio. È probabile che, se ti trovi a Londra, o in Russia, o negli Stati Uniti, il tuo orologio non è proprio corretto per quei posti. Il tuo orologio segna il momento sbagliato per il resto del mondo, e per alcuni luoghi anche la data sbagliata. Quando parli di "il mondo", avere un appuntamento senza un tempo non ha molto senso quando inizi a considerare persone al di fuori del tuo fuso orario. Pensa solo a quanto è fastidioso andare su un sito Web di uno straniero e vedere che, in qualche modo, l'utente ha generato contenuti che provengono dal futuro. Questo è quello che succede quando non prendi in considerazione i fusi orari!

Ecco dove entra C # DateTime.

DateTime non è la solita semplice data di cui potresti aver bisogno per il software locale, just-my-company. Si tratta di una struttura di dati un po 'potente che aveva l'intento di essere in grado di fornire Universal Coordinated Time a qualsiasi app. La parte magica della struttura DateTime è che, con piccoli giochetti, è possibile farlo visualizzare il DateTime corretto per ogni singolo posto nel mondo.

L'idea alla base di DateTime era di fornire non un semplice oggetto Date, ma qualcosa che potresti usare per rappresentare date in tutto il mondo, anche con diversi Fusi orari. È stato fatto pensando in applicazioni globali, e quindi è stato progettato con un sacco di funzionalità extra che potrebbero non avere apparente utilità a prima vista, ma tuttavia possono risparmiare molto tempo da persone che sviluppano applicazioni che dovranno gestire fusi orari variabili .

È tutt'altro che perfetto, sì, ma fa ciò per cui è stato concepito - rappresenta il tempo in un modo universale e un po 'portatile.

Quindi, in un certo senso, quando usi C # sei costretto a considerare i tempi durante lo sviluppo della tua app, non solo le date. E, davvero, questa è una buona cosa - un DateTime è un punto di riferimento nel tempo relativo a qualcosa e quando cambi il tuo punto di riferimento, il valore per quel DateTime deve agire di conseguenza.

Per essere totalmente onesto, penso che C # sia una delle lingue che ha fatto bene questa cosa. È possibile avere un intervallo di tempo senza una data (TimeSpan è lì per quello), ma non è possibile avere una data significativa su uno scope globale senza una cornice di riferimento e un'ora ad essa allegata. Non mi piaceva affatto DateTime quando ho incontrato la lingua, ma dopo aver sviluppato un'App con più fusi orari ho capito perché questa scelta progettuale era davvero intelligente.

    
risposta data 27.03.2017 - 22:16
fonte
2

Anthony Moore fornisce un post di blog con alcune note storiche in particolare su DateTime , inclusa una discussione sui tipi di problemi che Microsoft stava tentando di risolvere. È un po 'vecchio, ma offre comunque alcune informazioni.

La maggior parte dell'articolo è dedicata alla gestione dei problemi relativi al fuso orario e alla compatibilità con le versioni precedenti. Sembra che nel corso della storia delle versioni .NET Microsoft abbia compreso che lo spazio dei problemi è molto complesso e tutto ciò che hanno fatto sembra essere il risultato di un desiderio di compromesso tra ricchezza di funzionalità e semplicità. Ecco un bit interessante che sembra parlare (molto brevemente) del problema di una rappresentazione data-only:

First, consider the landscape of date and time related scenarios:

A. Legacy DateTime Interop (databases, COM, Win32, etc).

B. Abstract DateTime scenarios (e.g. store starting time).

C. Date-only scenarios.

D. Time-only scenarios.

E. Absolute time scenarios. (e.g. file time).

F. Server scenarios with dates from multiple time zones where the original local time must be retained.

Scenarios C-D might be even better handled by dedicated Date and Time types. These options are still on the table, although they will not be in the .NET 3.5 release.

Quindi sembra che abbia preso in considerazione un tipo di dati Date ed era ancora sul tavolo quando questo blog è stato scritto. Un po 'più di spiegazione può essere trovata altrove nell'articolo:

There was a lot of desire to keep the type system simple, and while a time zone aware DateTime was better at representing absolute points in time such as a file time-stamp, it got awkward when doing certain things....Representing whole dates, e.g. the type for a calendar control to return. Obviously a “Date” type is an even better way of representing this, and many people have asked for separate Date and Time types, but in V1.0 there was a desire to keep the number of base types small to limit complexity of the platform. This feature request is definitely still on the table, although not planned for .NET 3.5

Quindi penso che la risposta sia ... sì, ci hanno pensato ... no, non l'hanno ancora fatto, perché solleva alcuni problemi e c'è il desiderio di mantenere semplice la piattaforma complessiva.

Nel frattempo, hanno rilasciato il nuovo DateTimeOffset struttura, che risolve alcuni dei problemi relativi al fuso orario. Ma non tutti i problemi relativi alla data. Speriamo che i problemi relativi alla sola data saranno esaminati in seguito.

    
risposta data 28.03.2017 - 21:36
fonte
1

Non esiste una classe di questo tipo nelle librerie standard CLR, ma spesso c'è bisogno di una cosa del genere, per i motivi che hai identificato e altri.

Puoi importare la libreria "Noda" per C # e utilizzare LocalDate per rappresentare una data senza un tempo specifico.

Questa classe è basata su una classe simile dalla libreria Java "Joda", che è risultata così utile e ben scritta che ora è stata importata nelle librerie standard Java: LocalDate

Quando converti da LocalDate (senza un tempo) a% standardDateTime (con un componente temporale), la libreria ti obbliga a rendere esplicite le tue ipotesi, in modo da evitare tutti i tipi di casi limite ed errori che hai identificato nella tua domanda e nella discussione sulla risposta di T. Sar

    
risposta data 09.10.2018 - 16:33
fonte
-1

Sì, le proprietà C # possono essere attribuite solo per emettere la data:

[XmlElement("EndDt", DataType = "date", IsNullable = true)]
public DateTime? EndDate { get; set; }


public bool ShouldSerializeEndDate()
{
    return EndDate.HasValue;
}

Per evitare problemi relativi al fuso orario, utilizza le date UTC.

Se vuoi solo la data nel codice usa EndDate.Date .

    
risposta data 27.03.2017 - 22:09
fonte

Leggi altre domande sui tag