Get time object from the web?

J

Jose Wong

Hello there.
I was wondering if, it was possible to connect to the internet and
create a time object (Time.new) from a web clock?
 
J

Jeff Peng

Hello there.
I was wondering if, it was possible to connect to the internet and
create a time object (Time.new) from a web clock?

It depends on what the web clock is.
If you can get the time arguments from it (like day, month, year,hour,
minute, second etc), you could use Time.local to create a time object.

HTH.
Jeff.
 
A

Albert Schlef

Jose said:
Hello there.
I was wondering if, it was possible to connect to the internet and
create a time object (Time.new) from a web clock?

Instead of using NTP you can simply download some page, via HTTP, from a
webserver whose clock you trust to be sufficiently accurate. Servers
send a Date header, which you can use.

Example from the shell:

wget -q -d -O /dev/null http://google.com 2>&1 | grep ^Date
 
C

Colin Bartlett

SK> another way:
SK> http://juretta.com/log/2006/08/26/ruby_contacting_a_timeserver/

In that URL cited, there is a comment that reads
=A0# you might want to cache the Cache result... it won't change ;-)

What does this mean?

The code (full code is below for ease of reference) says that
the time server returns the number of seconds from 1900-01-01.
The Ruby Time class works with the number of seconds
from 1970-01-01, so to use the seconds to create a Time object
we need to adjust the seconds returned from the time server
by the number of seconds from 1900-01-01 to 1970-01-01.
That number of adjustment seconds won't change,
so once it has been calculated using get_seconds_diff_1970_1900
that adjustment can be stored for future use.

So you could do something like:
adjustment_secs_1900_to_1970 =3D get_seconds_diff_1970_1900
and then
seconds =3D Net::Telnet.new(options).recv(4).unpack('N').first
remote_time =3D Time.at( seconds - adjustment_secs_1900_to_1970 )

Does that explain what you were asking about?


## code at http://juretta.com/log/2006/08/26/ruby_contacting_a_timeserver/
require 'net/telnet'
TIME_SERVER =3D 'ntp2.fau.de'

options =3D {
"Host" =3D> TIME_SERVER,
"Telnetmode" =3D> false,
"Timeout" =3D> 30,
"Port" =3D> "time"
}

# The time is the number of seconds since 00:00 (midnight) 1 January 1900
# GMT, such that the time 1 is 12:00:01 am on 1 January 1900 GMT; this
# base will serve until the year 2036.
seconds =3D Net::Telnet.new(options).recv(4).unpack('N').first

# The Ruby Time class handles dates with an epoch
# starting at midnight january 1 1970
# We have to use the Date class to work with pre-epoch dates.
require 'date'
def get_seconds_diff_1970_1900
# you might want to cache the Cache result... it won't change ;-)
(DateTime.new(1970, 1, 1) - DateTime.new(1900, 1, 1)).to_i * 24 * 60 * 60
end

# Convert seconds to a Time object
remote_time =3D Time.at(seconds - \
get_seconds_diff_1970_1900).strftime("%Y-%m-%d %H:%M:%S")

print "Time from #{TIME_SERVER} -> #{remote_time}"
 
J

Jose Wong

Great! It seems to work, but, can someone help me for making a class
with that code, that will return that time object? Like this:

@now = ServerTime.get_time

@now is now the time object returned by that server...

I'm very new to Ruby, but I do know it is great :O
 
C

Colin Bartlett

Great! It seems to work, but, can someone help me for making a class
with that code, that will return that time object? Like this:
@now = ServerTime.get_time
@now is now the time object returned by that server...

The following seems to work, but it *isn't* "production code"
because it doesn't deal with timeouts or other failures,
which should perhaps return nil or raise an exception.

# based on code at
http://juretta.com/log/2006/08/26/ruby_contacting_a_timeserver/
require "net/telnet"

class ServerTime
attr_reader :host
TIME_SERVER = 'ntp2.fau.de'
# 25567 = 70 * 365 + 70.div(4); this is *not* a general formula
# for converting periods of years to seconds: leap years need
# careful handling; also this ignores leap seconds.
SECONDS_1900_01_01_TO_1970_01_01 = 25567 * 24 * 60 * 60

def initialize( host_v = nil )
@host = host_v || TIME_SERVER
@options = {
"Host" => @host,
"Telnetmode" => false,
"Timeout" => 30,
"Port" => "time"
}
end

# Note that this does *not* deal with what happens if there is a timeout
# or other failure to get the time from the time server.
def time()
# The time is the number of seconds since 00:00 (midnight) 1 January 1900
# GMT, such that the time 1 is 12:00:01 am on 1 January 1900 GMT; this
# base will serve until the year 2036.
seconds = Net::Telnet.new(@options).recv(4).unpack('N').first
Time.at( seconds - SECONDS_1900_01_01_TO_1970_01_01 )
end
end

st = ServerTime.new
t = st.time
puts "Time from #{st.host} -> #{t}"
sleep 3
puts "Time from #{st.host} -> #{st.time}"
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,160
Messages
2,570,889
Members
47,423
Latest member
henerygril

Latest Threads

Top