Datum / Zeit      
 

 Datum u. Zeit in Visual Basic

Dieser Artikel befasst sich mit der Verarbeitung von Datums-/Zeit-Angaben in VB.
Codebeispiele zeigen das Arbeiten mit dem Datentyp Date

 Datum u. Zeit in SQL-Strings

Beispiele für SQL-Strings zur Abfrage von Werten nach Datums- / Zeitkriterien

 
 

  isDateExt (strDate As String, Fmt As String)

Erweiterung der VB-Funktion isDate() zur Überprüfung von Datumsausdrücken auf ein bestimmtes vorgebbares Format.
  

 
 

 GetTimeFromServer

Zeit von einem beliebigen Rechner im Netzwerk holen.

 Feiertage

Ein kleines VB-Programm zum Ermitteln der Feiertage eines Jahres.

 
           
 

 

 

 

 
  Feiertage

 

Bewegliche und feste Feiertage

VB-Programm zum Ermitteln der 
beweglichen und festen Feiertage

 

 

Download
Projekt FTage.vbp
(FTage.zip 4kb

 
           
      
   Get Time From Server

 

GetTimeFromServer

Lesen der Systemzeit eines entfernten Rechners im Netzwerk.

Mit Hilfe der APi-Funktion NetRemoteTOD() lässt sich die Systemzeit eines Rechners in einem Netzwerk auslesen. Dies kann z.B. sehr nützlich sein, um Datum/Uhrzeit aller Rechner in einem LAN zu synchronisieren. 

' /// Code in einem Standardmodul *.bas

Option Explicit

Private Type TIME_OF_DAY
    tod_elapsedt As Long
    tod_msecs As Long
    tod_hours As Long
    tod_mins As Long
    tod_secs As Long
    tod_hunds As Long
    tod_timezone As Long
    t_tinterval As Long
    t_day As Long
    t_month As Long
    t_year As Long
    t_weekday As Long
End Type

Private Declare Function NetRemoteTOD _
Lib "NETAPI32.DLL" _
(ByVal server As String, _
Buffer As Any) As Long

Private Declare Function NetApiBufferFree _
    Lib "NETAPI32.DLL" _
    (ByVal Buffer As Long) As Long

Private Declare Sub CopyMemory _
    Lib "kernel32" Alias "RtlMoveMemory" _
    (hpvDest As Any, _
    hpvSource As Any, _
    ByVal cbCopy As Long)


Public Function GetTimeFromServer(ByVal LogonServer As String) As Date

    'Fragt das aktuelle Datum sowie die Uhrzeit von Logonserver ab

    Dim TOD As TIME_OF_DAY
    Dim TPtr As Long
    Dim lngRet As Long
    Dim todays As Date

    'ServerName nach Unicode konvertieren
    LogonServer = StrConv(LogonServer, vbUnicode)

    lngRet = NetRemoteTOD(LogonServer, TPtr)

    If lngRet = 0 Then

        'kopieren Daten von TPtr nach TOD
        CopyMemory TOD, ByVal TPtr, Len(TOD)

        'Speicher freigeben
        NetApiBufferFree (TPtr)

        'Die in TOD.xxx vorhandene Datums/Zeit- Information muss _
        um den ebenfalls in TOD.tod_timezone bereitgestellte Wert _
        korrigiert werden. (Datum/Zeit - TOD.tod_timezone (in Minuten))

        GetTimeFromServer = DateAdd _
            ("n", -TOD.tod_timezone, _
            DateSerial(TOD.t_year, TOD.t_month, TOD.t_day) _
            + TimeSerial _
            (TOD.tod_hours, TOD.tod_mins, TOD.tod_secs))
        
    Else
        MsgBox "NetRemoteTOD Fehler: " & lngRet
        GetTimeFromServer = 0
    End If
End Function

' \\\ Ende Code Standardmodul

Aufruf der Funktion:

    Debug.Print GetTimeFromServer("\\Rechnername")
oder
    Debug.Print GetTimeFromServer("Rechnername")

Wird für "Rechnername" ein leerer String ("") übergeben, so wird die Zeit des eigenen Rechners zurückgegeben
 

 
      

 

           
           
 

 
Datum / Zeit in VisualBasic

Für Datums- und Zeitangaben stellt VisualBasic den Datentyp Date zur Verfügung.

In seinem Aufbau entspricht der Datentyp Date dem Datentyp Double.
Ein Datum (mit evtl. zusätzlicher Zeitangabe) wird, sofern es als Datentyp Date definiert ist, intern als Zahl vom Datentyp Double gespeichert.

Dabei gilt folgende Vereinbarung:
Vor dem Komma wird die Anzahl Tage seit dem 30. Dezember 1899 angegeben, der Wert nach dem Komma gibt die Uhrzeit an.

Der 30. Dezember 1899 00:00:00 Uhr wird durch die Zahl 0 dargestellt.
Der 30. Dezember 1899 12:00:00 Uhr wird durch die Zahl  0,5 dargestellt.

Mit der Umwandlungsfunktion cDate( ) kann ein gültiger Datumsausdruck in ein Datum vom Datentyp Date umgewandelt werden.
Datumsausdrücke die mit cDate( ) umgewandelt werden können sind z.B.:
"1. Januar 2000"
"1. Januar 2000 15:36:35"
"1.1.2000"
"1.1.00"
usw.
Ebenso können Werte vom Typ Double in ein Datum umgewandelt werden.
cdate(36526.5) ergibt das Datum 1.1.2000 12:00:00
(siehe hierzu auch Online-Hilfe zu VB:
     Format$,
     benannte Datumsformate,
     benutzerdefinierte Datumsformate)

Bei nur zweistelliger Angabe des Jahres in einem umzuwandelnden Datumsausdruck wird nach folgender Regel verfahren:

Windows 95/98:
Jahr 00 bis Jahr 29 wird als Jahr 2000 bis Jahr 2029 interpretiert.
Jahr 30 bis Jahr 99 wird als Jahr 1930 bis Jahr 1999 interpretiert.

Bei Windows ME, Windows 2000 u. Windows XP ist die Zuordnung bei zweistelligen Jahresangaben in der Systemsteuerung (Ländereinstellung/Datum) einstellbar.


cDate(
"1. Januar 2000 12:00:00") ergibt die Zahl 36526,5 .
Wird nun versucht diese Behauptung mit Debug.Print cDate("1. Januar 2000 12:00:00") nachzuprüfen, so kann dies leicht zu einer falschen Vorstellung vom Datentyp Date führen.
Mit Debug.Print cDate("1. Januar 2000 12:00:00") erhält man nämlich "01.01.00 12:00:00".
Debug formatiert das aus cDate( ) erhaltene Datum gleich wieder entsprechend den für das System geltenden Datumseinstellungen.

Mit Debug.Print cDbl(cDate("1. Januar 2000 12:00:00")) erhält man das wahre Ergebnis mit 36526,5 .

Mit Hilfe des Datentyps Date lassen sich auch Datums/Zeit-Angaben vor dem 30.12.1899 darstellen. Tage die vor dem 30.12.1899 liegen erhalten einfach ein negatives Vorzeichen.
Debug.Print cDBL(cDate("29.12.1899")) ergibt -1.

Ein Datum sollte also immer als Datentyp Date verarbeitet werden. Beim Speichern eines Datums in einer Datenbank sollte immer der Datentyp Date verwendet werden, um Probleme wie sie bei unterschiedlich formatieren Strings auftreten können von vorneherein zu vermeiden..


Ein mit dem Datentyp Date (Zahl mit x Stellen vor dem Dezimaltrennzeichen für das Jahr und Stellen nach dem Dezimaltrennzeichen für die Uhrzeit) gespeichertes Datum kann mit Hilfe der Funktionen cDate( ) und Format$( ) in jedem gewünschten Format wieder ausgegeben werden

Format$(36526.5,"dd.mm.yyyy hh:nn:ss") ergibt "01.01.2000 12:00:00"
Format$(36526.5,"dddd, d. mmmm yyyy hh:nn:ss") ergibt "Samstag, 1. Januar 2000 12:00:00"
(Bei der Angabe der Zahl 36526.5 muss wie immer bei Zahlen in VB als Dezimaltrennzeichen der Punkt verwendet werden)

Manchmal werden Datumsangaben im amerikanischen Datumsformat mit umgebenden Nummernzeichen (#) benötigt. Auch hier helfen cDate ( ) und Format$( ) weiter.

Mit Hilfe von Format$(cDate("31.12.1999"),"\#mm\/dd\/yyyy\#") wird aus dem Ausdruck "31.12.1999" der Ausdruck "#12/31/2002#".
Das Zeichen Backslash (\) im vorangegangenen Formatstring der Format$-Funktion besagt, dass das jeweils nachfolgende Zeichen so wie es ist übernommen werden soll.
"\#" ergibt im Beispiel also erst mal das führende Nummernzeichen.
"mm" bewirkt die daran anschließende Ausgabe des Monats im zweistelligen Format.
"\/" (kein V, sondern Backslash und Schrägstrich) bewirken die Ausgabe des ersten / nach dem Monat.
"dd" bewirkt die nachfolgende Ausgabe des Tages mit zwei Stellen.
"\/" (Backslash und Schrägstrich) erzeugt den Schrägstrich nach dem Tag.
"yyyy" bewirkt die 4-stellige Ausgabe des Jahres.
"\#" erzeugt das abschließende # (Nummernzeichen).

 

 
       
           
           
           
 

 
Datumsausdrücke in SQL Strings

Ein immer wieder auftauchendes Problem ist die Angabe eines Datums in einem SQL-String zur Abfrage einer Datenbanktabelle.
Das folgende Beispiel zeigt, wie ein bestimmter Zeitraum aus der Tabelle Bestellungen der Nordwind Datenbank selektiert werden kann.

Option Explicit
Dim mWS As Workspace
Dim mDB As Database
Dim mDBFileName As String

'Auf der Form befinden sich folgende Steuerelemente:
    DataControl:            Data1
    Textbox:                  txtVon
    Textbox:                  txtBis
    CommandButton:     Command1
    DBGrid:                   DBGrid1

'Einstellung zur Designzeit:
   DBGrid1.DataSource = Data1


Private Sub Form_Load()
    Dim SQL as String
    'Textfelder leeren _
    das hierbei ausgelöste _Change-Ereignis _
    sperrt Command1.
    txtVon.Text = ""
    txtBis.Text = ""
    'Command1 beschriften
    Command1.Caption = "Start"
    'Pfad zur Nordwind Datenbank NWIND.MDB
    mDBFileName = "D:\Microsoft Visual Studio\VB98\NWIND.MDB"
    'Workspace erstellen
    Set mWS = DBEngine.CreateWorkspace("MyWS", "Admin", "")
    'Datenbank öffnen
    Set mDB = mWS.OpenDatabase(mDBFileName, False, False)
    'SQL-String zur Ausgabe der gesamten Tabelle
    SQL = "SELECT * FROM Bestellungen"
    'Recordset für Data1 öffnen
    Set Data1.Recordset = mDB.OpenRecordset(SQL, dbOpenDynaset)
    'hiermit zeigt DBGrid nach dem Programmstart _
    zuerst die gesamte Tabelle Bestellungen.
End Sub

Private Sub Command1_Click()
    Dim SQL As String
    SQL = "SELECT * FROM Bestellungen WHERE Bestelldatum BETWEEN " & _
                Str$(CDbl(CDate(txtVon.Text))) & _
                " AND " & _
                Str$(CDbl(CDate(txtBis.Text)))
    'Recordset für Data1 öffnen
    Set Data1.Recordset = mDB.OpenRecordset(SQL, dbOpenDynaset)
    'DBGrid zeigt damit nur die in den Textfeldern _
    txtVon / txtBis angegebene Auswahl an Datensätzen
End Sub

'Command1 abhängig von txtVon/txtBis freigeben/sperren
Private Sub txtBis_Change()
    Command1.Enabled = (IsDate(txtVon.Text) And IsDate(txtBis.Text))
End Sub

Private Sub txtVon_Change()
    Command1.Enabled = (IsDate(txtVon.Text) And IsDate(txtBis.Text))
End Sub

Private Sub txtVon_KeyPress(KeyAscii As Integer)
    If KeyAscii = vbKeyReturn Then
        KeyAscii = False
        If IsDate(txtVon.Text) Then
            'falls txtVon ein gültiges Datum enthält, _
            weitergehen zum Feld txtBis

            txtBis.SetFocus
        End If
    End If
End Sub

Private Sub txtBis_KeyPress(KeyAscii As Integer)
    If KeyAscii = vbKeyReturn Then
        KeyAscii = False
        If Command1.Enabled Then
            'ist nur erfüllt, wenn beide Textfelder _
            ein gültiges Datum enthalten

            Command1_Click
        End If
    End If
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
   'Routine zum Schliessen aller noch existierenden _
    Recordsets u. Datenbanken

    Do While mWS.Databases.Count > 0
        Do While mWS.Databases(0).Recordsets.Count > 0
            mWS.Databases(0).Recordsets(0).Close
        Loop
        mWS.Databases(0).Close
    Loop
End Sub

Nach dem Programmstart wird in die Textfelder txtVon ... txtBis der gewünschte Zeitraum eingegeben.
Command1 wird nur freigegeben, wenn beide Felder ein gültiges Datum enthalten.
Durch einen Klick auf Command1 (Start) wird die Datenbankabfrage gestartet.

SQL-Server und Jet-Engine erkennen Datumsausdrücke in SQL-Strings auch im amerikanischen Datumsformat. Der im vorangegangenen Beispiel verwendete SQL-String könnte auch durch den folgenden ersetzt werden:

SQL = "SELECT * FROM Bestellungen WHERE Bestelldatum BETWEEN " & _
            Format$(CDate(txtVon.Text), "\#m\/d\/yyyy\#") & _
            " AND " & _
            Format$(CDate(txtBis.Text), "\#m\/d\/yyyy\#")

Ebenso werden vom SQL-Server und der Jet-Engine Datumsausdrücke im ISO-Format erkannt:

SQL = "SELECT * FROM Bestellungen WHERE Bestelldatum BETWEEN " & _
            Format$(CDate(txtVon.Text), "\#yyyy\/mm\/dd\#") & _
            " AND " & _
            Format$(CDate(txtBis.Text), "\#yyyy\/mm\/dd\#")
 

 
 
       
           
           
           
 

 
isDateExt()

Die VB-Funktion isDate() erkennt Datumsausdrücke der verschiedensten Formate. Häufig ist es erwünscht, einen Datumsausdruck auf ein ganz bestimmtes Format hin zu überprüfen.

Public Function isDateExt(strDate As String, Fmt As String) As Boolean
    If IsDate(strDate) Then
    isDateExt = (strDate = Format$(strDate, Fmt))
    End If
End Function

'Aufruf der Funktion:

Dim strFmt as String
strFmt = "dd.mm.yyyy"

if IsDateExt("23.09.2001", strFmt ) then
    ' MsgBox "Datum OK"
else
    MsgBox "Datum bitte nur im Format '"& strFmt & "'"
end if


'Die Funktion gibt nur dann True zurück, wenn der im ersten Paramter übergebene Datumsausdruck exakt das vorgegebene Format einhält. Im Beispiel also zweistelligen Tag, zweistelliges Monat,
vierstelliges Jahr.