This tutorial describes three different Shift time intervals. The first is a simple object, that divides the plant day into a fixed number of equal-length shifts, which start at a set of specified times. It does not support named members: the shifts are simply numbered from 1 to n. For this example, n = 3, but the code is written to be easily adapted to more or fewer shifts.
Because this is a custom interval server, to be used in one locale only, there is no localization code.
Shift implements the ITimeIntervals interface.
Open the code window for the Shift class and add these statements:
‘Shift class ' This statement brings all the defined properties ' and methods of the ITimeInterval ' interface into this class.
Implements PITimeServer.ITimeInterval 'Constants ' These constants are the name, plural name, ' and abbreviated name of the interval, which ' the SDK will use in parsing time arithmetic expressions. Private Const cName = "Shift" Private Const cPluralName = "Shifts" Private Const cShortName = "sh" ' These constants are the lowest and highest ordinal ' numbers supported by this time interval. Private Const cMemberLo = 1 Private Const cMemberHi = 3 ' These constants give the number of shifts and the length of a shift. Private Const cNumShifts As Integer = 3 Private Const cShiftLen As Date = 1# / cNumShifts
No class initialization or termination routine is necessary.
Insert the following routines:
Private Sub CheckDate(dt As Date) If dt < #1/1/1970# Or CDbl(dt) >= 2958466 Then _ Err.Raise tseDATEOUTOFRANGE, cName, _ "Date must be between 1-Jan-1970 and 31-Dec-9999" End Sub
CheckDate checks a Date to see if it is in the valid range for the PI SDK. If not, it raises an error. It will be used by each property or method that returns a Date, to validate the result before returning it.
Private Sub STOrd(pTime as PITime, _ LocaleIndependent As Boolean, STime as Date, Ord as Long) Dim ti as ITimeInterval Set ti = New PlantDay STime = pd.StartTime(pTime, LocaleIndependent) Ord = 1 Do While (pTime.LocalDate – STime) > cShiftLen STime = STime + cShiftLen Ord = Ord + 1
Loop End Sub
STOrd calculates both the start time and ordinal number for a shift, using an auxiliary PlantDay object. The StartTime and Ordinal properties use this routine.
Choose ITimeInterval on the code window’s left-hand drop-down. Then, in turn, choose each of the properties and methods on the right-hand drop-down, and insert the following code into them (VB-supplied code in gray):
Private Property Get ITimeInterval_Name( _ Optional ByVal LocaleIndependent As Boolean = False) As String ITimeInterval_Name = cName End Property Private Property Get ITimeInterval_PluralName( _ Optional ByVal LocaleIndependent As Boolean = False) As String ITimeInterval_PluralName = cPluralName End Property Private Property Get ITimeInterval_ShortName( _ Optional ByVal LocaleIndependent As Boolean = False) As String ITimeInterval_ShortName = cShortName End Property
Private Property Get ITimeInterval_MemberHi() As Long ITimeInterval_MemberHi = cMemberHi End Property Private Property Get ITimeInterval_MemberLo() As Long ITimeInterval_MemberLo = cMemberLo End Property
This time interval does not support named members. Therefore both MemberName and MemberShortName raise Visual Basic error 445, which is the equivalent of the error code E_NOTIMPL .
Private Property Get ITimeInterval_MemberName( _ ByVal Index As Long, _ Optional ByVal LocaleIndependent As Boolean = False) As String Err.Raise 445, cName, "Interval " & cName & _ " does not have named members" End Property Private Property Get ITimeInterval_MemberShortName( _ ByVal Index As Long, _ Optional ByVal LocaleIndependent As Boolean = False) As String Err.Raise 445, cName, "Interval " & cName & _ " does not have named members" End Property
Private Function ITimeInterval_AddIntervals( _ lang=FR style='color:gray;mso-ansi-language:FR'> ByVal pTime As PITimeServer.PITime, _ ByVal nIntervals As Double) As Date Dim retval As Date retval = pTime.LocalDate + nIntervals / cNumShifts CheckDate retval ITimeInterval_AddIntervals = retval End Function
Private Property Get ITimeInterval_StartTime( _ ByVal pTime As PITimeServer.PITime, _ Optional ByVal LocaleIndependent As Boolean = False) As Date Dim STime As Date Dim Ord as Long STOrd pTime, LocaleIndependent, STime, Ord CheckDate STime ITimeInterval_StartTime = STime End Property Private Property Get ITimeInterval_Ordinal( _ ByVal pTime As PITimeServer.PITime, _ Optional ByVal LocaleIndependent As Boolean = False) As Long Dim STime As Date Dim Ord as Long STOrd pTime, LocaleIndependent, STime, Ord ITimeInterval_Ordinal = Ord End Property
FindMember behaves much the same as for the PlantDay object. It is a little simpler, because its Index argument must be a number. If Index cannot be converted to a number, VB raises a type mismatch error. We let VB pass this error on to the caller.
Private Function ITimeInterval_FindMember( _ ByVal Time As PITimeServer.PITime, _ ByVal Index As Variant, _ Optional ByVal WhatToFind As _ PITimeServer.FindIntervalConstants = 1&, _ Optional ByVal LocaleIndependent As Boolean = False) As Date Dim dt As Date 'start of the base interval Dim iStep As Integer 'direction to search Dim iShift As Integer 'shift to search Dim retval As Date 'return value Dim iix As Long 'integer index of desired interval Dim delta As Integer 'number of days difference from base If Not IsNumeric(Index) Then Err.Raise 5, cName, "Interval " & cName _ & " does not have named members" Else iix = Index 'raise error if Index is not a number If iix < cMemberLo Or iix > cMemberHi Then Err.Raise 5, cName, "Index out of range" End If End If delta = iix – ITimeInterval_Ordinal(pTime) Select Case WhatToFind 'adjust delta as required Case fiBefore If delta >= 0 Then delta = delta - cNumShifts Case fiOnOrBefore If delta > 0 Then delta = delta - cNumShifts Case fiAfter If delta <= 0 Then delta = delta + cNumShifts Case fiOnOrAfter If delta < 0 Then delta = delta + cNumShifts End Select retval = ITimeInterval_StartTime(pTime) + delta * cShiftLen CheckDate retval ITimeInterval_FindMember = retval End Function