5 Replies Latest reply on May 11, 2011 7:39 PM by charlie@osisoft.com

    Start and end times for RecordedValues using Server Time.

    IOMHouston

      I have a requirement to perform all operations in "Server" time.

       

      In oleDB, there is an extended property (Time Zone) that allows you to specify that all queries are in "servertime", and all data returned will reflect server time. The query behaves as if the server was local.

       

      Is it possible to do this with the .NET API's

       
      PISDK.PIValues piValues = piPoint.Data.RecordedValues("*13/01/2911 19:23:34", "*",
      PISDK.BoundaryTypeConstants.btInside,"",
      PISDK.FilteredViewConstants.fvShowFilteredState, null);
      

       Is there a way to indicate that that 19:23:34 is server time?
      And that the values in the piValues are in ServerTime

       

      On a side note -> I can get the time from

       
      PISDK.PIValue v = piValues[ii];
      v.TimeStamp.
      

       You can get UTC and local time from this TimeStamp object.
      How can I get the serverTime from this object.
      Do calculations have to be manual (UTC to server time).

       

      Thanks

        • Re: Start and end times for RecordedValues using Server Time.

          Yes, this is built into the PISDK by the using PITimeServer.DynamicTime.  The ClockSource property accepts the Server objects' IClockSource interface, which then makes all time parsing relative to the Server.ServerTime clock source.

           
          private void FetchData(PISDK.Server sv, PISDK.PIData pidat, string st, string et)
          {
              // Declare the time objects outside any loops - why recreate each time?
              PITimeServer.DynamicTime pitm1 = new PITimeServer.DynamicTime();
              PITimeServer.DynamicTime pitm2 = new PITimeServer.DynamicTime();
              // The clock source references the server TAI/UTC time.
              pitm1.SetClockSource((PITimeServer.IClockSource)sv);
              // The server time zone may be different.  '*' means the same regardless of TZ,
              // but 'T', or a 'local time' should be evaluated in the target TZ.
              pitm1.TimeZoneInfo = ((PITimeServer.IClockSource)sv).TimeZoneInfo;
              pitm2.SetClockSource((PITimeServer.IClockSource)sv);
              pitm2.TimeZoneInfo = ((PITimeServer.IClockSource)sv).TimeZoneInfo;
          
              // DynamicTime detects that only one 'T' occurs per day, so only evaluates once.
              pitm1.InputString = "T"; 
              // DynamicTime reevaluates '*' whenever a 'get' property is called.
              pitm2.InputString = "*";
          
              // Prepare for non-blocking call
              PISDKCommon.PIAsynchStatus asynch = new PISDKCommon.PIAsynchStatus();
              PISDKCommon.IPIAsynchStatus2 asynch2 = (PISDKCommon.IPIAsynchStatus2)asynch;
              Microsoft.Win32.SafeHandles.SafeWaitHandle hdone =
                          new Microsoft.Win32.SafeHandles.SafeWaitHandle((IntPtr)asynch2.CallCompleteEvent, false);
              // PISDK 1.4.0 only; returns ulong instead of int
              //PISDKCommon.IPIAsynchStatus3 asynch3 = (PISDKCommon.IPIAsynchStatus3)asynch;
              //Microsoft.Win32.SafeHandles.SafeWaitHandle hdone =
              //    new Microsoft.Win32.SafeHandles.SafeWaitHandle((IntPtr)asynch3.CallCompleteEvent2, false);
              System.Threading.AutoResetEvent hwait = new System.Threading.AutoResetEvent(false);
              hwait.SafeWaitHandle = hdone;
          
              //PISDK.PIValues pivals = pidat.RecordedValues(pitm1, pitm2, PISDK.BoundaryTypeConstants.btInside);
              PISDK.PIValues pivals = pidat.RecordedValues(pitm1, pitm2, PISDK.BoundaryTypeConstants.btInside,
                          "", PISDK.FilteredViewConstants.fvShowFilteredState, asynch);
                      hwait.WaitOne();
              if (asynch.Status == PISDKCommon.CallStatusConstants.csComplete)
              {
                  // use the data
              }
              else
              {
                  // error reporting
              }
          }
          

           

           

          You should also notice that the time zone may be set independently of the UTC time

            • Re: Start and end times for RecordedValues using Server Time.
              IOMHouston

              Just to verify your response. The timestamps in the returned PIValues list will still be in UTC time? I would have to calculate an offet to display the values in server time right. Are thre helper methods which will display the PIValue.Timestamp in server time. Code samples as above would be very cool.

               

              Thanks.

                • Re: Start and end times for RecordedValues using Server Time.
                  PITimeServer.PITimeFormat ptf = new PITimeServer.PITimeFormatClass();
                  ptf.FormatString = "MM-dd hh:mm:ss.000";
                  //ptf.TimeZoneInfo = srv.PITimeZoneInfo;
                  int lenvalue = 26;
                  listBox1.Items.Clear();
                  foreach (PISDK.PIValue pv in pivals)
                  {
                     string strtemp;
                     ptf.UTCSeconds = pv.TimeStamp.UTCSeconds;
                     strtemp = ptf.OutputString;
                     strtemp += "; ";
                     strtemp += ValueToString(pv.Value, DisplayDig);
                     // attempt to align the values in the listbox
                     if (strtemp.Length > lenvalue)
                        lenvalue = strtemp.Length;
                     else
                     {
                        int idx, ldelta = lenvalue - strtemp.Length;
                        for (idx = 0; idx < ldelta; idx++) strtemp += " ";
                     }
                     PISDKCommon.NamedValues valattr = pv.ValueAttributes;
                     if (valattr.Count > 0)
                        strtemp += GetValAttrString(valattr);
                      listBox1.Items.Add(strtemp);
                  }
                  

                   

                   

                  UTC time is passed when values are sent to or retrieved from the PI Server.  The time object that translates to/from UTC on the client node imposes it's time zone rules (PITime, PITimeFormat, DateTime, VT_DATE, etc).  Thus, the input strings above are translated to UTC on the client before making the RecordedValues call (thus the need for the DynamicTime to put the timestamps in the server frame of reference).  The returned PIValue has a PITime object that will give you back UTC time or translate to LocalDate (DateTime) using the client TZ rules.  If you want to translate to a time zone other than the client - the PI Server's in your request, then PITimeFormat may be used.  Note, the UTC timestamp of a PIvalue is immutable, but the time zone in which it may be displayed can be chose according to user preferences by setting the PITimeFormat.TimeZoneInfo property to the chose time zone.

                   

                  I found another code snippet from a test program to format a timestamp.  This example uses the default time zone (inherits from the OS).  If you wish to allow another time zone, the PITimeFormat.TimeZoneInfo property must be set.