Access-o-Mania

Access-Forum (Deutsch/German) => Tabelle/Abfrage => Thema gestartet von: masterofdisaster am März 12, 2012, 14:00:17

Titel: Anzahl Stunden je Monat aus Anfangs- und Enddatum
Beitrag von: masterofdisaster am März 12, 2012, 14:00:17
Ich habe zwei Felder [DatVon] und [DatBis] im Format "dd.mm.yyy hh:mm:ss"
Angenommen der Wert für [DatVon] ist 21.01.2012 06:00:00 und der Wert [DatBis] ist 04.03.2012 12:00:00

Nun möchte ich die Anzahl Stunden berechnen, die in den Monat Januar, Februar und März fallen. Dabei sollen Sommer- und Winterzeit sowie Schaltjahre (z.B. 29.02.2012) berücksichtigt werden!

Die Anzahl Stunden für die gesammte Dauer konnte ich bereits mit der Funktion DatDiff() errechnen.

Besten Dank und Grüsse
Titel: Re: Anzahl Stunden je Monat aus Anfangs- und Enddatum
Beitrag von: DF6GL am März 12, 2012, 14:40:17
Hallo,

setze vor der (gleichen) Berechnung einfach das DatumVon auf den Ersten des Monats und DatumBis auf den letzten des Monats (z. B. mit der Dateseriell-Funktion).


Ob dabei die Sommer/Winterzeit berücksichtigt wird (Du meinst sicherlich das Fehlen einer Stunde bezgl. des Umstelltermins) ist mir jetzt nicht bekannt. Evtl. muss diese "Fehlzeit" separat in die  Berechnung eingebaut werden.


Titel: Re: Anzahl Stunden je Monat aus Anfangs- und Enddatum
Beitrag von: masterofdisaster am März 16, 2012, 08:09:20
verstehe was du meinst, aber wie kann ich das effektiv in Access umsetzen?
Hat jemand eine Idee?
Titel: Re: Anzahl Stunden je Monat aus Anfangs- und Enddatum
Beitrag von: daolix am März 16, 2012, 16:40:17
Probier es mal so:
'// --------------------------------------------------------------------------------------------------
'// --< UDT's >--
'// --------------------------------------------------------------------------------------------------
Type SYSTEMTIME
    wYear As Integer
    wMonth As Integer
    wDayOfWeek As Integer
    wDay As Integer
    wHour As Integer
    wMinute As Integer
    wSecond As Integer
    wMilliseconds As Integer
End Type

Type TIME_ZONE_INFORMATION
    Bias As Long
    StandardName(31) As Integer
    StandardDate As SYSTEMTIME
    StandardBias As Long
    DaylightName(31) As Integer
    DaylightDate As SYSTEMTIME
    DaylightBias As Long
End Type


'// ----------------------------------------------------------------------------------------------------------------
'// --<   >--
'// ----------------------------------------------------------------------------------------------------------------
Private Declare Function VariantTimeToSystemTime Lib "OLEAUT32.DLL" _
    ( _
        ByVal vbtime As Double, _
        ByRef lpSystemTime As SYSTEMTIME _
    ) _
    As Long
   
'// ----------------------------------------------------------------------------------------------------------------
'// --<   >--
'// ----------------------------------------------------------------------------------------------------------------
Private Declare Function SystemTimeToVariantTime Lib "OLEAUT32.DLL" _
    ( _
        ByRef lpSystemTime As SYSTEMTIME, _
        ByRef vbtime As Double _
    ) As Long
   
'// ----------------------------------------------------------------------------------------------------------------
'// --<   >--
'// ----------------------------------------------------------------------------------------------------------------
Declare Function GetTimeZoneInformation Lib "KERNEL32.DLL" _
    ( _
        ByRef lpTimeZoneInformation As TIME_ZONE_INFORMATION _
    ) As Long

'// ----------------------------------------------------------------------------------------------------------------
'// --<   >--
'// ----------------------------------------------------------------------------------------------------------------
Declare Function TzSpecificLocalTimeToSystemTime Lib "KERNEL32.DLL" _
    ( _
        ByRef lpTimeZoneInformation As TIME_ZONE_INFORMATION, _
        ByRef lpLocalTime As SYSTEMTIME, _
        ByRef lpUniversalTime As SYSTEMTIME _
   ) As Long
   
   
'// ----------------------------------------------------------------------------------------------------------------
'// --< Konstanten >--
'// ----------------------------------------------------------------------------------------------------------------
Const TIME_ZONE_ID_INVALID = &HFFFFFFFF


Public Function HoursPerMonth(ByVal v As Date, ByVal b As Date) As String
    Dim a As Date, e As Date, aa As Date, ee As Date
    Dim lst As SYSTEMTIME, ust As SYSTEMTIME, bst As SYSTEMTIME
    Dim TZI As TIME_ZONE_INFORMATION
    Dim dbl As Double
    Dim s As String

    If GetTimeZoneInformation(TZI) <> TIME_ZONE_ID_INVALID Then
        a = v
        Do
            e = DateSerial(Year(a), Month(a) + 1, 1) + TimeSerial(0, 0, 0)
            If e > b Then e = b
            dbl = a: GoSub Sub_MkUTC: aa = dbl
            dbl = e: GoSub Sub_MkUTC: ee = dbl
            s = s + Format$(a, "mmm") + vbTab + Str$(DateDiff("h", aa, ee)) + vbCrLf
            If e = b Then Exit Do
            a = e
        Loop
    End If
   
Sub_Exit:
    HoursPerMonth = Left$(s, Len(s) - 2)
    Exit Function

Sub_MkUTC:
    VariantTimeToSystemTime dbl, lst
    TzSpecificLocalTimeToSystemTime TZI, lst, ust
    SystemTimeToVariantTime ust, dbl
    Return
End Function


Aufgerufen wirds dann in etwa so:
HoursPerMonth "21.01.2012 06:00:00", "04.03.2012 12:00:00"

Titel: Re: Anzahl Stunden je Monat aus Anfangs- und Enddatum
Beitrag von: masterofdisaster am März 20, 2012, 13:31:35
Super, der Code funktioniert einwandfrei und die Berechnungen stimmen.
Wie kann ich nun lediglich den Wert z.B. für einen Monat, sagen wir März als Übergabeparameter, ausgeben; und zwar als Integer, um damit weitere Berechnungen anzustellen?
Titel: Re: Anzahl Stunden je Monat aus Anfangs- und Enddatum
Beitrag von: daolix am März 20, 2012, 16:54:16
Die Funktion HoursPerMonth ist wie folgt umzuschreiben:
Public Function HoursPerMonth(ByVal v As Date, ByVal b As Date, ByVal m As Long, Optional ByVal y As Long) As Single
    Dim a As Date, e As Date, aa As Date, ee As Date
    Dim lst As SYSTEMTIME, ust As SYSTEMTIME
    Dim TZI As TIME_ZONE_INFORMATION
    Dim dbl As Double

    If GetTimeZoneInformation(TZI) <> TIME_ZONE_ID_INVALID Then
        a = v
        Do
            e = DateSerial(Year(a), Month(a) + 1, 1) + TimeSerial(0, 0, 0)
            If e > b Then e = b
            dbl = a: GoSub Sub_MkUTC: aa = dbl
            dbl = e: GoSub Sub_MkUTC: ee = dbl
            If Month(a) = m And (Year(a) = y Or y = 0) Then
                HoursPerMonth = (e - a) * 24
                Exit Do
            End If
            If e = b Then Exit Do
            a = e
        Loop
    End If
   
Sub_Exit:
    Exit Function

Sub_MkUTC:
    VariantTimeToSystemTime dbl, lst
    TzSpecificLocalTimeToSystemTime TZI, lst, ust
    SystemTimeToVariantTime ust, dbl
    Return
End Function

Die Rückgabe erfolgt hier als single um auch evtl minuten zu erfassen.

Der aufruf  ist dann ähnlich:
HoursPerMonth( "21.01.2012 06:00:00", "04.03.2012 12:00:00", 3)
optional kann auch noch das Jahr angegeben werden falls der gegebene Zeitraum größer einem Jahr ist.
Titel: Re: Anzahl Stunden je Monat aus Anfangs- und Enddatum
Beitrag von: MzKlMu am März 20, 2012, 18:34:04
Hallo,
ZitatDie Rückgabe erfolgt hier als single um auch evtl minuten zu erfassen.
Ich würde hier Double nehmen, für Minuten ist Single meiner Meinung nach zu ungenau, da 1/60 = 0,016 Periode 6 ergibt, entstehen mit Single zu große Rundungsfehler.
Titel: Re: Anzahl Stunden je Monat aus Anfangs- und Enddatum
Beitrag von: daolix am März 20, 2012, 19:20:48
Hallo
Jup könnte man auch, aber der Rundungsfehler ist jetzt auf die reine Minute bezogen nicht wirklich gross, er liegt bei 2/10000, d.h. die Minute(n) wird/werden richtig berechnet.  Auch mit Double enstehen Rundungsfehler, so dass für weitere Berechnungen auch diese ggf gekürtzt werden müssten. Aber stimmt schon im Normalfall nimmt man Double oder cDec.
masterofdisaster wollte den Return ja nur als Integer/Long was für seine Fragestellung auch gereicht hätte.
Titel: Re: Anzahl Stunden je Monat aus Anfangs- und Enddatum
Beitrag von: masterofdisaster am März 21, 2012, 08:52:45
Perfekt! Genau das habe ich gebraucht.
Nochmals vielen Dank.