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
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.
verstehe was du meinst, aber wie kann ich das effektiv in Access umsetzen?
Hat jemand eine Idee?
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"
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?
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.
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.
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.
Perfekt! Genau das habe ich gebraucht.
Nochmals vielen Dank.