none
[Access 2007] Problem mit Datumsformat?

    Frage

  • Hallo,

    meine C#-Applikation sendet, auf Basis von GUI-Input, Abfragen an meine Access 2003-DB und visualisiert die Ergebnismenge.

    Nun will ich das Tool samt DB einem Kollegen zur Verfuegung stellen. Alles funktioniert, solange kein Datum-Kriterium in den WHERE-Teil des Commandstrings kommt.

    Auf meinem Rechner ist Access 2003 installiert, auf seinem lediglich Access 2007.

    Hat jemand eine Idee?

    MfG und Danke fuer alle Vorschlaege

    Flux

    Sonntag, 10. Februar 2013 22:09

Antworten

  • Hallo Flux 1989

    Genau das ist der Grund, dass es nicht geht.

    Die Ländereinstellung dient zur Präsentation der Daten in Access. Diese wird auch berücksichtigt, wenn Datentypen z.B. über Format ohne Angabe des expliziten Datumsformats konvertiert werden. Das Datumsformat "Short Date" (oder "Datum kurz") wird also in das Datum umwandeln,d as in der Ländereinstellung vorgegeben ist. Die Jet Engine dahinter interessiert sich nicht daran und erwartet das Datum in einem einheitlichen Format, unabhängig von der Ländereinstellung. Teilweise ist für Dich Access dazwischen geschaltet, welches ja dann eben die Präsentation übernimmt, aber wenn das nicht der Fall ist, ist niemand da, der das Deutsche Datumsformat in das Datenbank Datumsformat umwandelt und dann scheitert die Datenbank Engine eben daran, das Datum richtig zu interpretieren. Diese erwartet nämlich das unsinnige US-englische Format MM/DD/YYYY HH:NN:SS, also genau umgekehrt mit Monaten und Tagen. Jet kann allerdings dann eben auch mit YYYY-MM-DD umgehen, es erkennt automatisch, dass es sich hier um ein "vernünftiges" Datumsformat handelt.

    Wenn Du bei deinem Kollegen das US Englische Datumsformat einstellst, wird es vermutlich funktionieren. Nur gilt das dann eben Systemweit und er wird da keine Freude dran haben. Daher nochmals die Empfehlung, das Datum händisch in das Format YYYY-MM-DD HH:NN:SS umzuwandeln und dann auf die Jet Engine loszulassen. Dann interessiert es nicht, was an der Oberfläche eingestellt ist. Die Jet Engine speichert das sowieso dann als Double in der Tabelle in der Datenbank ab, nur die Präsentation der Daten sieht aus wie ein Datum.

    Gruss

    Henry

    • Als Antwort markiert Flux1989 Samstag, 23. Februar 2013 18:05
    Donnerstag, 14. Februar 2013 03:19

Alle Antworten

  • Das Format des Datums ist nicht eindeutig. Wenn jemand auf englisches Datum eingestellt hat, dann kann das zweite Datum entweder als 7. Februar oder 2. Juli interpretiert hat. Basis ist dabei das Datumsformat in der Ländereinstellung (Regionale Einstellungen).

    DAs einfachste ist, wenn Du das Datum in der From #YYYY-MM-DD HH:NN:SS# benutzt. Dann bist Du unabhängig von den Ländereinstellungen.

    Gruss

    Henry


    Montag, 11. Februar 2013 02:52
  • "DAs einfachste ist, wenn Du das Datum in der From #YYYY-MM-DD HH:NN:SS# benutzt."

    Ok, ich muss schauen, ob das ohne probleme geht. Wo müsste ich denn auf dem Rechner meines Kollegen überall die Sprache umstellen, sodass das als deutsches Datumsformat interpretiert wird ?

    Danke und viele Grüße

    Flux


    • Bearbeitet Flux1989 Montag, 11. Februar 2013 19:35
    Montag, 11. Februar 2013 19:35
  • Hallo,

    Flux1989 wrote:

    [Henry]

    "DAs einfachste ist, wenn Du das Datum in der From #YYYY-MM-DD HH:NN:SS#
    benutzt."

    Ok, ich muss schauen, ob das ohne probleme geht. Wo müsste ich denn auf
    dem Rechner meines Kollegen überall die Sprache umstellen, sodass das
    als deutsches Datumsformat interpretiert wird ?

    Systemsteuerung - Region und Sprache - Formate

    Aber das hilft nur so lange, bis jemand die Einstellung wieder aendert,
    daher ist Henrys Vorschlag der bessere Weg.
    Gruss - Peter


    Mitglied im http://www.dbdev.org
    FAQ: http://www.donkarl.com

    Montag, 11. Februar 2013 20:24
    Moderator
  • wie bereits erwähnt in der Ländereinstellung (in der Systemsteuerung)

    Gruss

    Henry

    Dienstag, 12. Februar 2013 02:00

  • "DAs einfachste ist, wenn Du das Datum in der From #YYYY-MM-DD

    Systemsteuerung - Region und Sprache - Formate 

    So ich hab nun die Systemeinstellungen meines Kollegen inspiziert und bin etwas erstaunt, da entgegen meiner Erwartung das deutsche Datumsformat eingestellt war.

    Und nu??

    Mittwoch, 13. Februar 2013 22:36
  • Hallo Flux 1989

    Genau das ist der Grund, dass es nicht geht.

    Die Ländereinstellung dient zur Präsentation der Daten in Access. Diese wird auch berücksichtigt, wenn Datentypen z.B. über Format ohne Angabe des expliziten Datumsformats konvertiert werden. Das Datumsformat "Short Date" (oder "Datum kurz") wird also in das Datum umwandeln,d as in der Ländereinstellung vorgegeben ist. Die Jet Engine dahinter interessiert sich nicht daran und erwartet das Datum in einem einheitlichen Format, unabhängig von der Ländereinstellung. Teilweise ist für Dich Access dazwischen geschaltet, welches ja dann eben die Präsentation übernimmt, aber wenn das nicht der Fall ist, ist niemand da, der das Deutsche Datumsformat in das Datenbank Datumsformat umwandelt und dann scheitert die Datenbank Engine eben daran, das Datum richtig zu interpretieren. Diese erwartet nämlich das unsinnige US-englische Format MM/DD/YYYY HH:NN:SS, also genau umgekehrt mit Monaten und Tagen. Jet kann allerdings dann eben auch mit YYYY-MM-DD umgehen, es erkennt automatisch, dass es sich hier um ein "vernünftiges" Datumsformat handelt.

    Wenn Du bei deinem Kollegen das US Englische Datumsformat einstellst, wird es vermutlich funktionieren. Nur gilt das dann eben Systemweit und er wird da keine Freude dran haben. Daher nochmals die Empfehlung, das Datum händisch in das Format YYYY-MM-DD HH:NN:SS umzuwandeln und dann auf die Jet Engine loszulassen. Dann interessiert es nicht, was an der Oberfläche eingestellt ist. Die Jet Engine speichert das sowieso dann als Double in der Tabelle in der Datenbank ab, nur die Präsentation der Daten sieht aus wie ein Datum.

    Gruss

    Henry

    • Als Antwort markiert Flux1989 Samstag, 23. Februar 2013 18:05
    Donnerstag, 14. Februar 2013 03:19
  • Hallo,

    Flux1989 wrote:

    "DAs einfachste ist, wenn Du das Datum in der From #YYYY-MM-DD

    Systemsteuerung - Region und Sprache - Formate 

    So ich hab nun die Systemeinstellungen meines Kollegen inspiziert und
    bin etwas erstaunt, da entgegen meiner Erwartung das*deutsche
    Datumsformat* eingestellt war.

    Klar, das ist ja die Ursache fuer die falsche Datumsinterpretation in
    deiner Abfrage.

    Da hatte ich die Erklaerung wohl zu kurz gefasst, Henry hat das aber
    nachgeholt. Stell testweise als Datumsformat MM/DD/YYYY ein (oder MM/DD/YY,
    jeweils mit dem Schraegstrich als Trennzeichen). Deine Abfrage wird
    funktionieren, aber dein Kollege wird nicht zufrieden sein ;-)

    Gruss - Peter


    Mitglied im http://www.dbdev.org
    FAQ: http://www.donkarl.com

    Donnerstag, 14. Februar 2013 11:28
    Moderator
  • Hallo Peter und Henry,

    erstmal danke für eure schnellen Antworten. Ich möchte nun euren Rat befolgen und sowohl DB-seitig (Access2003) als auch GUI-seitig (C#-Applikation) anpassen. Was ich euren Beiträgen entnehmen konnte*: ich soll das Format YYYY-MM-DD HH:NN:SS verwenden.
    Nun, welche Einstellungen nehme ich in der Access-DB für die Datumsspalte am besten vor. Danach ist zu klären, wie der entsprechende Datentyp in C# dafür heisst.

    Am stabilsten scheint mir der Ansatz alles von der Speicherungs- bis zur Anzeigeschicht systemsprachenunabhaengig zu gestalten. Nehmen wir mal folgendes Setup an:

    1. (WinForms) DateTimePicker <--> 2. (C#) Programmcode <--> 3. SQL-Statement <--> 4. (Access03) Datenzelle

    Auf der 1. Ebene waehle ich das CustomFormat:

    DateTimePicker1.CustomFormat = "dd MMM yyyy"; //z. B. 28 Feb 2011

    2. Ebene:

    DateTimePicker1.Value.ToString() faellt aufgrund der sprachabhaengigkeit weg.

    Ich koennte aber DateTimePicker1.Value.Day, DateTimePicker1.Value.Month, DateTimePicker1.Value.Year beliebig miteinander verhackstueckeln zwecks Formatierung

    Alternativ koennte ich auch sagen: dateTimePicker1.Value.ToOADate() --> da wird dann aber leider eine fuer Menschen unlesbare Zahl draus gemacht. Will man mal per Access in die DB schauen, dann saehe man nur lauter kryptischer Zahlen in der Datumsspalte :(

    3. Schicht: SQL-Syntax

    AFAIK braucht Access03 zwingend die Lattenzaeune ums #Datum#, sonst schlaegt der SQL-Ausdruck fehl.

    4.Schicht: Datenspeicherung in der DB

    Je nach Systemsprache scheint Access03 die Anzeige eines Datums zu anzupassen (hatte grad Systemsprache auf EN ==> Datum wird in Access im Format MM/dd/YYYY angezeigt. Danach auf GER umgestellt ==> dd.MM.YYYY), was darauf schliessen laesst, dass im Hintergrund ein Datum sowieso als kryptischer Double(?)-Wert abgelegt wird (oder Henry?). Welchen Sinn hat also die Datumsformat-Einstellung in Access fuer mich?

    Viele Wege fuehren nach Rom, aber welcher ist am pragmatischsten?

    Viele Grüße
    Flux

    *Danke Henry für die ausführliche Antwort, aber irgendwie bin ich nicht wirklich schlau daraus geworden, weil mir die verschiedenen Schichten und wer was wie warum interpretiert nicht klar sind.

    • Bearbeitet Flux1989 Samstag, 23. Februar 2013 01:06 darum
    Freitag, 22. Februar 2013 22:16
  • Hallo Leute,

    habs hinbekommen, siehe folgender Test-Code. Auf der Anzeigeschicht verwende ich das Custom-Format "ddd, dd MMM yyyy", im Code baue ich mir aus der Eingabe ein Datum nach dem Format "yyyy/MM/dd" zusammen und verwende dies sowohl bei Lese- (SELECT...) und Schreib- (INSERT INTO...) Zugriffen. In der Access-DB scheint sowieso ein sprachunabhaengiger Double-Wert (Ticks seit 19xx) abgelegt zu sein, welcher in der Access-GUI von der Windows-API (sprachabhaengig formatiert) angezeigt wird, aber das stoert ja nicht.

    Damit bin ich vollstaendig sprachUNabhaengig, oder?

    Vielen Dank fuer euere Beitraege

    namespace DatumTest
    {
        public partial class Form1 : Form
        {
            string cmdStr = String.Empty;
            string datum = String.Empty;
    
            public Form1()
            {
                InitializeComponent();
                dateTimePicker1.Format = DateTimePickerFormat.Custom;
                dateTimePicker1.CustomFormat = "ddd, dd MMM yyyy"; //Anzeigeformat: z. B. "Sa, 23 Feb 2013" (dadurch sind Monat und Tag eindeutig erkennbar)
            }
    
            private void button1_Click(object sender, EventArgs e) //Laden-Button
            {
                DateTime dt = dateTimePicker1.Value; //sprachabhaengig: liefert 23.02.2013 17:25:18 (DE) bzw. 02/23/2013 5:25:18 PM (EN)
                datum = dt.Year + "/" + dt.Month + "/" + dt.Day; //sprachUNabhaengig: 2013/02/23
                cmdStr = "SELECT * FROM datums WHERE datum = #" + datum + "#";
    
                listBox1.Items.Add(dateTimePicker1.Value);
    
                string conStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Users\\JB\\Desktop\\datum_db.mdb;";
                using (OleDbConnection con = new OleDbConnection(conStr))
                {
                    OleDbCommand cmd = new OleDbCommand(cmdStr, con);
                    con.Open();
    
                    OleDbDataReader dr = cmd.ExecuteReader();
    
                    while (dr.Read())
                    {
                        listBox1.Items.Add("\n\t" + ((DateTime)dr["Datum"]).ToShortDateString());
                    }
                }
            }
    
            private void button2_Click(object sender, EventArgs e) //Speichern-Button
            {
                DateTime dt = dateTimePicker1.Value; //sprachabhaengig: liefert 23.02.2013 17:25:18 (DE) bzw. 02/23/2013 5:25:18 PM (EN)
                datum = dt.Year + "/" + dt.Month + "/" + dt.Day; //sprachUNabhaengig: 2013/02/23
               
    
                string conStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Users\\JB\\Desktop\\datum_db.mdb;";
                using (OleDbConnection con = new OleDbConnection(conStr))
                {
                     cmdStr = "SELECT ID FROM Datums ORDER BY ID DESC";
                    OleDbCommand cmd = new OleDbCommand(cmdStr, con);
                    con.Open();
                    //ID
                    int maxID = (int) cmd.ExecuteScalar();
    
                    //Neuer Eintrag
                    cmd.CommandText = "INSERT INTO Datums VALUES (" + (maxID+1) + ", #" + datum + "#)";
                    listBox1.Items.Add("Status:" + cmd.ExecuteNonQuery());
                }
            }
        }
    }



    • Bearbeitet Flux1989 Samstag, 23. Februar 2013 18:02
    Samstag, 23. Februar 2013 18:01
  • Hallo,

    Flux1989 wrote:

    [...] welche Einstellungen nehme ich in der Access-DB für die
    Datumsspalte am besten vor.

    Datum/Zeit

    Am stabilsten scheint mir der Ansatz alles von der Speicherungs- bis zur
    Anzeigeschicht systemsprachenunabhaengig zu gestalten.

    Korrekt!

    [...]
    2. Ebene:

    DateTimePicker1.Value.ToString() faellt aufgrund der sprachabhaengigkeit weg.

    Genau, wie auch auf den anderen Ebenen mit Ausnahme der Anzeigeschicht.

    Alternativ koennte ich auch sagen: dateTimePicker1.Value.ToOADate() -->
    da wird dann aber leider eine fuer Menschen unlesbare Zahl draus
    gemacht. Will man mal per Access in die DB schauen, dann saehe man nur
    lauter kryptischer Zahlen in der Datumsspalte :(

    Das Datum wird in Access als serielle Zahl gespeichert, wobei vor dem Komma
    die Tage seit dem 30.12.1899 (= Tag 0) gezaehlt werden und nach dem Komma
    die Uhrzeit als Bruchteil eines Tages. Deshalb kommt in jeder Sprache und
    jedem Datumsformat das richtige Datum an der Oberflaeche an.

    3. Schicht: SQL-Syntax

    AFAIK braucht Access03 zwingend die Lattenzaeune ums #Datum#, sonst
    schlaegt der SQL-Ausdruck fehl.

    Korrekt. An den # erkennt Jet, dass ein Datum im Format YYYY-MM-DD bzw.
    MM-DD-YYYY folgt, wobei zwingend weder die Anzahl Stellen fuer Jahr/ Monat/
    Tag noch das Trennzeichen, sondern nur die Reihenfolge vorgeschrieben sind.

    4.Schicht: Datenspeicherung in der DB

    Je nach Systemsprache scheint Access03 die Anzeige eines Datums zu
    anzupassen (hatte grad Systemsprache auf EN ==> Datum wird in Access im
    Format MM/dd/YYYY angezeigt. Danach auf GER umgestellt ==> dd.MM.YYYY),
    was darauf schliessen laesst, dass im Hintergrund ein Datum sowieso als
    kryptischer Double(?)-Wert abgelegt wird (oder Henry?).

    Was die interne Speicherung angeht, siehe oben. Der Datentyp Datum/Zeit
    entspricht von der Groesse her einem Double.

    Welchen Sinn hat also die Datumsformat-Einstellung in Access fuer mich?

    Sie dient zur Darstellung des Datumswertes innerhalb der
    Access-Oberflaeche. Als serielle Zahl wirst du das Datum nur sehen, wenn du
    gezielt ein Zahlenformat fuer das Datum auswaehlst, z.B. Standard, oder
    #,##0.00
    Wenn kein Format angegeben ist, verwendet Access das Format, das in der
    Systemsteuerung eingestellt ist.

    Gruss - Peter


    Mitglied im http://www.dbdev.org
    FAQ: http://www.donkarl.com

    Sonntag, 24. Februar 2013 08:09
    Moderator