I like the custom DR option too, but then again I am a big fan of AF SDK and quite guilty of the saying "If all you have is a hammer, then eventually everything else starts to look like nail." But there are lots of details to work out if you choose the DR route.
These analyses will have to be periodically scheduled to run every hour. Or at least it would be easier. Otherwise you will need to have lots of extra code for your DR to implement AFEventSource in order for an analysis to be event triggered from your DR. Besides, just because the DR converts to a different time zone, doesn't mean the DR was triggered by some other data event. Rather the DR is based on a wall clock somewhere, and produces a value when requested. That is a pull, not a push, which means Periodic not Event triggered.
Elaborating on things you already know, but for others to read. Your AF Server is centrally located, and presumably this is the same server where all the analyses will execute. The problem to overcome here is that any trigger time for analyses will be local to the AF Server, not a remote site. Attempting to schedule with time zone offsets will not work year round due to DST transitions, again in different parts of the globe.
What do you want your DR to return? A DateTime object? Keep in mind that it typically returns with its Kind property set to Utc or Local, but for different remote sites you would want Kind to be Unspecified.
What if the DR returned an ISO 8601 string? The problem here is parsing that string to a DateTime or AFTime object inside an analysis, and then you are back to where we were in the previous paragraph.
Another option would be to have the DR return just the time portion, perhaps as a TimeSpan object. Or maybe just return an integer representing the Hour in the remote local time. Then your trigger just checks for 6. This would make the conditional much easier. Keep in mind that a remote site in Australia could return 6 but it would be 6:00 the next day in relation to a US based server.
Thanks for your thoughts! It indeed helps to add some more context to the problem.
Indeed i would schedule the analysis to run every 15 minutes (oddities: Half Hour and 45-Minute Time Zones , so that should be good enough without being a drain on resources).
The custom DR would return a DateTime object, Kind=Unspecified. That way i can then use standard analytics functions to pull out e.g. hours and minutes to determine if my production day started (which may be a different set of rules). I prefer that above ISO8601 strings or anythen else as i a DateTime would provide the most functionality. There might be some pitfalls, but that's why one would build and execute tests, so i think that's manegable.
Only thing to tell users is for them not to start days, shifts, etc. in the middle of a DST shift... Not all problems can be solved!
1 of 1 people found this helpful
I've been thinking more about this. You are smart enough to know what to test and how to test. I don't foresee an issue with a DR returning a DateTime object as the Value property, even if the Kind is Unspecified. What does make me curious is whether the Hour() function works on an AFTime or a DateTime object internally. If it works off only an AFTime, then the DateTime Value would be implicitly cast to AFTime, and since had Kind==Unspecified, it would then be treated as Utc, which could throw off the calculation.
Well, now to find some time between the stuffed turkey and the champagne to build and execute a test as proof of the pudding!
Finally had the priority to dig into this. Simply i take the time context provided to the DataReference, and use that to Convert the time:
targetZone = TimeZoneInfo.FindSystemTimeZoneById(strTargetTimezone); outputTime = TimeZoneInfo.ConvertTime(inputTime.UtcTime, targetZone); result.Value = outputTime;
Not finished yet with testing behaviour, but some preliminary conclusions:
- all AFTime constructors when casted into a DateTime result in .Kind=Unspecified
- when the time is casted back in the last line, this is assumed to be UTC as you indicated, and shows in a DateTime attribute moved back to the client timezone.
- When i use the Hour function in analytics however, the Hour is interpreted differently and i get a different result.
- Local timezone: UTC+1
- Current local time: 11:22:33
- Target Timezone: Greenwich Standard Time (so meaning result should be 10:22:33)
- Result in debugger before passing back to AF: 10:22:33, Kind=Unspecified
- Result as shown in PSE, datetime attribute: 11:22:33
- Result (Hour) as returned by the Hour() function: 10
So your gut feeling that the implicit casting would cause issues turned out to be right! Now to experiment to find a way to return a result that is reliably cast inside AF.
1 of 1 people found this helpful
Finally had the time to finish this. Essentially, i take the time from the timecontext provided, and move the time to a different timezone using TimezoneInfo.ConvertTime(). That outputs a time in datetimekind=unspecified, leading to different results in PSE and Analytics. Setting the datetimeKind to UTC ensures both PSE and Analytics make the correct assumptions on the datetime received. Configuration input is the .NET standard timezone name.
//Set result value targetZone = TimeZoneInfo.FindSystemTimeZoneById(strTargetTimezone); //ConvertTime assumes first parameter = UTC if kind is unspecified (which it is...) DateTime testKind = inputTime; convertTime = TimeZoneInfo.ConvertTime(inputTime.UtcTime, targetZone); //convertTime.Kind = Unspecified outputTime = DateTime.SpecifyKind(convertTime.ToUniversalTime(), DateTimeKind.Utc); result.Value = outputTime; //outputTime.Kind = Unspecified, and this assumed to be UTC. When displayed in cast back to localtime, time is
Thanks again Rick for this essential pointer!
Thank you for the persistence; I'm sure others will stumble across this over time and find it very helpful.
Just now reading the thread...
In regards to the half hour and 45 minute time zones, being from Canada and have Newfoundland be 30 minutes off from Atlantic time, the running joke was:
the world will end at 3:00 PM Atlantic Standard Time, 2:30 PM in Newfoundland.