The Shift Class

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.

Globals

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

Class Initialization

No class initialization or termination routine is necessary.

Helper Functions

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.

Properties and Methods

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):

Name, PluralName, ShortName

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

MemberHi, MemberLo

Private Property Get ITimeInterval_MemberHi() As Long
  ITimeInterval_MemberHi = cMemberHi
End Property

Private Property Get ITimeInterval_MemberLo() As Long
  ITimeInterval_MemberLo = cMemberLo
End Property

MemberName, MemberShortName

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

AddIntervals

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

StartTime, Ordinal

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

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

Save Your Project

Next
Enabling Operational Intelligence