Monday, September 08, 2008    
Home My Books Blog ColdFusion About Me Back    

Calendar
<< Dec 2005 >>
S M T W T F S
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
             

Search

Categories
 • Acrobat (2) [RSS]
 • Adobe (67) [RSS]
 • AdobeMAX06 (45) [RSS]
 • AdobeMAX07 (59) [RSS]
 • AdobeMAX08 (22) [RSS]
 • AIR (126) [RSS]
 • Appearances (118) [RSS]
 • Books (68) [RSS]
 • CFEclipse (14) [RSS]
 • ColdFusion (1143) [RSS]
 • Data Services (12) [RSS]
 • Fish Tank (2) [RSS]
 • Flash (103) [RSS]
 • Flex (365) [RSS]
 • Home Automation (3) [RSS]
 • Jobs (93) [RSS]
 • JRun (12) [RSS]
 • Labs (27) [RSS]
 • LiveCycle (21) [RSS]
 • MAX (157) [RSS]
 • Regular Expressions (12) [RSS]
 • RIA (4) [RSS]
 • SQL (37) [RSS]
 • Stuff (503) [RSS]
 • Tips (CF Studio) (80) [RSS]
 • Tips (CF) (795) [RSS]
 • Tips (Dreamweaver) (91) [RSS]
 • Tips (Flex Builder) (2) [RSS]
 • Using CF (136) [RSS]
 • Wireless (97) [RSS]

Other BLOGs
 • Charlie Arehart
 • Lee Brimelow
 • Ray Camden
 • Christophe Coenraets
 • Sean Corfield
 • Mihai Corlan
 • Cornel Creanga
 • John Dowdell
 • Danny Dura
 • Enrique Duvos
 • Steven Erat
 • Kevin Hoyt
 • Serge Jespers
 • Adam Lehman
 • Duane Nickull
 • Miti Pricope
 • Andrew Shorten
 • Ryan Stewart
 • James Ward
 • Greg Wilson
 • Full As A Goog

RSS Feeds
 • Feed
 • Subscribe

Join my mailing list and find out about new books and other topics of interest.

Thoughts, ideas, tips, musings, and pontifications (not necessarily in that order) by Ben Forta ...
NOTE: This is my personal blog, and the opinions and statements voiced here are my own.

Viewing By Day : December 6, 2005 / Main
December 6, 2005

ColdFusion UDF To Access NIST Time Servers

A developer asked me how he could get absolutely accurate time information for an application that he is working on. He cannot rely on local server time as he has no control over the machine, and can't verify that it is accurate (and can't change the time if not). There is no NTP (network time protocol) tag in ColdFusion, but fortunately one is not needed, because the NIST time servers also respond to plain text daytime protocol requests.

Here is a quick UDF I threw together to solve the problem. Call GetNISTTime() and it'll return a structure containing the raw data returned from the time server, as well as individual fields broken out for ease of use:

<!---

Name:         GetNISTTime()

Author:         Ben Forta, 12/6/2005

Description:   Obtains current time data from NIST
            Internet Time Service servers.

            DST:      US daylight savings time flag.
            HEALTHY:   TRUE if time server is healthy, FALSE if not.
            JULIAN:      Last 5 digits of Julian date/time value.
            LEAPMONTH:   TRUE is second will be added to or subtracted
                     from the current month.
            MSADV:      Number of milliseconds advanced by server to
                     compensate for network latency.
            NOW:      Current date/time.
            RAW:      Raw data from time server.
            SUCCESS:   TRUE if worked, FALSE if not, check
                     this flag first.

Note:         For a list of NIST time servers see:
            http://tf.nist.gov/timefreq/service/time-servers.html
            Servers should be addressed via IP address rather than
            host name. The server used here is time.nist.gov
            (192.43.244.18), but any of the listed servers will work.
            To use an alternate server, just specify the IP
            address in timeServer variable.
--->

<cffunction name="GetNISTTime" returntype="struct" output="false">
   <cfset var timeServer="192.43.244.18">
   <cfset var result=StructNew()>

   <!--- Try/catch block --->
   <cftry>

      <!--- Try get time data --->
      <cfhttp url="http://#timeServer#:13/" />
      <!--- Save raw data --->
      <cfset result.raw = CFHTTP.FileContent>
      <!--- Extract Julian date --->
      <cfset result.julian=ListGetAt(result.raw, 1, " ")>
      <!--- Extract current date and time --->
      <cfset result.now=ParseDateTime(ListGetAt(result.raw, 2, " ")
                              & " "
                              & ListGetAt(result.raw, 3, " "))>

      <!--- Extract daylight savings time flag --->
      <cfset result.dst=IIf(ListGetAt(result.raw, 4, " ") IS 0,
                        FALSE, TRUE)>

      <!--- Extract leap month flag --->
      <cfset result.leapmonth=IIf(ListGetAt(result.raw, 5, " ") IS 0,
                           FALSE, TRUE)>

      <!--- Extract health flag --->
      <cfset result.healthy=IIf(ListGetAt(result.raw, 6, " ") IS 0,
                           FALSE, TRUE)>

      <!--- Extract advance milliseconds --->
      <cfset result.msadv=ListGetAt(result.raw, 7, " ")>
      <!--- Success --->
      <cfset result.success=TRUE>

      <!--- Catch any errors --->
      <cfcatch type="any">
         <cfset result.success=FALSE>
      </cfcatch>

   </cftry>

   <cfreturn result>

</cffunction>

To test this code you can just use:

<cfset x=GetNISTTime()>
<cfdump var="#x#">

TrackBacks
There are no trackbacks for this entry.

No trackback URL. Trackbacks are only allowed via interactive form.

Comments
VERY NICE!
# Posted By Tuyen | 12/6/05 2:01 PM
Again... you achieve our praise. Just hope Adobe appreciates getting an Allaire veteran!
# Posted By John Farrar | 12/6/05 3:57 PM
Or if you can add .jar file to CF server /lib directory, then you can use some free SNTP lib like this one:

http://alpha.uhasselt.be/Research/Algebra/Members/...

And then use code like this:
<cfscript>
ntpServer = "time.nist.gov";
ntpConn = CreateObject("java", "be.ac.luc.vdbergh.ntp.NtpConnection");
ntpConn.init(CreateObject("java", "java.net.InetAddress").getByName(ntpServer));
time = ntpConn.getTime();
</cfscript>

<cfoutput>#time#</cfoutput>
# Posted By Erki Esken | 12/6/05 5:46 PM
Nice one. We just implemented something similar in my company. We're starting to have overseas clients (as opposed to aussie only before), so we needed to save absolute times in the DB yet display relative times to our customers. For example, if I buy something on an american website, I need to see the aussie purchase-date/time on my screen, and my customer rep needs to see the american one. In our case (e-recruitment) it's even more crucial, as we schedule interviews, invite candidates to tests and so on...
It's actually much trickier than it seems , mostly because of daylight savings. DS is chosen by governments and can change any year. It doesn't have to be a full hour, and it doesn't even have to be there at all.
Here in Oz, we have DS in victoria (melbourne), but not in Tasmania (the island). My point is, there is absolutely no way to calculate it, so you have to get the info somewhere. you could use a timeserver, but :
1.what if it goes down?
2.different business objects in our system can belong to different timezones, so we can't just save a time-offset once and for all in the session.

So what we did (not me but a guy here) was instanciate the java.util.TimeZone class that's shipped with JRun and contains all that info (updated everytime they update jrun I think). add a whole lot of small udfs to calculate offsets to the recipe, and that's a wrap. We did have a few load problems, apparently because we're still running on CF5 :-( which doesn't handle java as well as MX, but now it seems to be fine.

Any comment on this solution would be more than welcome. don't hesitate to tell me if I'm plain wrong about something because I'm a junior developer, and I didnt work on that project so I may be mistaken on some points.
# Posted By christophe | 12/6/05 6:13 PM
Christophe, when you move to CF7 then use Paul Hasting's excellent timezone CFC:
http://www.sustainablegis.com/projects/tz/testTZCF...

And read his cfg11n site, it has really good stuff on i18n/g11n/l10n and CF:
http://cfg11n.blogspot.com/
# Posted By Erki Esken | 12/6/05 7:18 PM
hey, thanks for that, it looks cool. We're actually going to re-design the application next year, using cf7 and machii (maybe flex2). And we're talking about a 300 000-lines app that has grown for 7 years. Can't wait to add OO and framework skills to my quiver!
# Posted By christophe | 12/6/05 8:07 PM
Errr...

What is the purpose of this:

<cfset result.leapmonth=IIf(ListGetAt(result.raw, 5, " ") IS 0,FALSE, TRUE)>

Wouldn't

<cfset result.leapmonth=ListGetAt(result.raw, 5, " ") NEQ 0>

Do the same without the added overhead of Iif()?
# Posted By Al Everett | 12/7/05 11:47 AM
Looks like result.now gives an incorrect date, the day and year get swapped. A simple fix is to change ParseDateTime to LSParseDateTime:

&lt;!--- Extract current date and time ---&gt;
<br >
&lt;cfset result.now=LSParseDateTime(ListGetAt(result.raw, 2, &quot; &quot;)
                &amp; &quot; &quot;
                &amp; ListGetAt(result.raw, 3, &quot; &quot;))&gt;
# Posted By Seth | 12/7/05 1:38 PM
@Al Everett:

I was about to post pretty much the exact same message as you.. that is until I saw your message :-) And I'm still curious to hear the answer of course :-)
# Posted By Auke van Leeuwen | 12/9/05 10:12 AM
Al, Auke, no reason, just kinda happened. :-) I had cfif statements while testing, and then turned it into an IIf(). But what you suggested will work just as well, maybe better.
# Posted By Ben Forta | 12/9/05 10:15 AM
Aight, just checking :-)

Btw: looking at the timestamps of these postings, it looks like your server could use some time synchronization :-D
# Posted By Auke van Leeuwen | 12/9/05 10:21 AM
Didn't IIF used to be significantly slower than <cfif>? Is that no longer the case?

In any event, I prefer not to use IIF for two reasons:

1. <cfif> tags are more readable
2. All three of the parts of an IIF need to be valid at run-time or it will throw an error, while <cfif> doesn't. For instance, this will bomb out: <cfset foo=iif(isDefined("variables.bar"),variables.bar,de("Not defined"))> if variables.bar is not defined, while this will not:
<cfif isDefined("variables.bar")>
<cfset foo=variables.bar>
<cfelse>
<cfset foo="Not defined">
</cfif>
# Posted By Al Everett | 12/9/05 1:37 PM
yep, supposedly, IIF is twice as slow as cfif. and much less readable, I'm with you!
# Posted By christophe | 12/11/05 4:54 PM
It has it's uses (IMHO).

...
<select name="selectBox">
<cfloop query="qQuery">
<option
value="#nID#
#iif( nID eq url.nParam, de( 'selected="selected"' ), de( '' ))#
>#sName#</option>
</cfloop>
</select>
...
# Posted By Auke van Leeuwen | 12/11/05 11:34 PM

  © Copyright 1997-2008 Ben Forta, All Rights Reserved