In my application I have a Server and x Clients. When a Client starts, he obtained the current System time from the Server. Every Client has to work with the Server time and can´t use his own System time.
Now my Question: What is the best way to run a clock on the Client that starts with the current Server time and run nearly synchronous to it without to receive the Server time every x seconds?
The goal is to display a runing clock with the Server time on the client.
The tolerance that the client clock may have is about 1second in 24hours.
In my solution I got a Timer that trigger every 500ms and count 500ms on the Server time when the Timer executes. But this is not a good solution :) because the Client clock differ from the Server time.
Thanks for your reply
You should almost certainly use an established clock synchronization method such as the Network Time Protocol rather than building your own custom solution. It will provide you with better results than you will make yourself, and you have the added benefit that all your servers agree about what time it is :-)
I find a Solution that fits perfectly for my situation.
Instead of using System.currentTimeMillis(), I'm using System.nanoTime().
System.nanoTime() is independent from the System clock.
When I receive the current Server time, I save additional the ns from the System. Then the current Server time will be calculated with the difference between the ns time from Server time receiving and the current nanoTime plus the Server time.
Example:
// The Client starts and receive the current Server time and the nanoTime
private long serverTime = server.getCurrentTime();
private long systemNano = System.nanoTime();
//To calculate the current Server time without a service call
//ns-> ms
long currentServerTime = serverTime + ((System.nanoTime() - systemNano) / 1000000);
Thx
One way to do this is to get the difference between the server time and the local time and use that for time calculations
The client starts and gets the time from the server (I am going to assume use the current time in milliseconds but this can be adapted to whatever you are using)
The client checks its current system time and saves the difference
The difference can then always be applied to the current system time on the client to calculate the server time
Example:
long serverTime = 1328860926471l; // 2012/02/10 10:02, received from wherever
long currentTime = System.currentTimeMillis(); // current client time
long difference = currentTime - serverTime;
// Server time can then me retrieved like this:
long currentServerTime = System.currentTimeMillis() - difference;
Date serverTimeDate = new Date(currentServerTime);
Obviously the difference must be saved the moment the server time is received.
Related
Using Java Flow Framework for SWF.
Any way to schedule an activity for a specific time in SWF?
Let's say, send run the "sendNotification" at 22nd Oct 2017 9:00 AM.
The examples allow to create timer with a delay, but not for the specified time.
Even though I can calculate the delay, based on the current time stamp and the target time when the event is needed to be fired, but how can I get the current time during workflow execution, since if you try to get the current system time in workflow decider, it creates non-determinism in workflow and it fails.
Date currentDate = new Date();
long sysTimeInSeconds = (currentDate.getTime() / 1000);
System.out.println("System Time : " + sysTimeInSeconds);
Promise<Void> timer = clock.createTimer((timeStampInSeconds - sysTimeInSeconds));
[ The above code is not allowed since we are using current time from system]
The current time of workflow clock, returns the start time of the workflow, which is of no use to me.
So how I can schedule an activity for a particular time ?
Use the WorkflowClock. It returns the correct deterministic current time which is the time of the decision being replayed.
Here is the line of code that updates clock to the current decision time.
What happens with running timers when a system time is changed?
I have an android application and I use handler.postDelayed(Runnable,interval) to post a Runnable to be called (the run() method) at the end of the interval.
The question I have is:
What happens if the underlying system time is changed externally?
My impression is that the posting still happens but at the time of system time change the countdown starts again... Can anybody shade some light here?
Does the behavior change if the time change is forwards or backwards?
First,you should know Handler is based on SystemClock.uptimeMillis().
Handlers sendMessageXXX() methods such as sendMessageDelayedăsendEmptyMessage all use the method below internal:
//calcute the milliseconds we hope to handle the message since the system was booted
sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis)
Then,the time interval value SystemClock.uptimeMillis() + delayMillis will be kept into Message's field when,and we put the message into the MessageQueue waiting for Looper to poll out it.
While the looper gets the next message from the queue,it will compare SystemClock.uptimeMillis() with msg.when to judge whether the message is ready.If the next message isnt ready,it will set a timeout to wake up until the msg is ready.
Second,you confuse SystemClock.uptimeMillis() with System.currentTimeMillis().Below is part of the documentation of SystemClock which explains the two concepts:
SystemClock.uptimeMillis() is counted in milliseconds since the system was booted. This clock stops when the system enters deep sleep (CPU off, display dark, device waiting for external input), but is not affected by clock scaling, idle, or other power saving mechanisms. This is the basis for most interval timing such as Thread.sleep(millls), Object.wait(millis), and System.nanoTime(). This clock is guaranteed to be monotonic, and is suitable for interval timing when the interval does not span device sleep.
System.currentTimeMillis() is the standard "wall" clock (time and date) expressing milliseconds since the epoch. The wall clock can be set by the user or the phone network (see setCurrentTimeMillis(long)), so the time may jump backwards or forwards unpredictably. This clock should only be used when correspondence with real-world dates and times is important, such as in a calendar or alarm clock application. Interval or elapsed time measurements should use a different clock. If you are using System.currentTimeMillis(), consider listening to the ACTION_TIME_TICK, ACTION_TIME_CHANGED and ACTION_TIMEZONE_CHANGED Intent broadcasts to find out when the time changes.
No it doesn't matter. If you dig around the code, the delay is provided by the following mechanism -
SystemClock.uptimeMillis() + delayMillis
So it is purely relative. And changing of system time has no effect on it
I need to better measure the detailed timing of a HTTP Request (connection time, time to first byte, transfer time).
Context:
I have a small java app (running on AWS Lambda) that is calling a third party service.
As the logging was showing big delays in the processing, a small piece of logging was added to better find out where the delays was happening:
HttpPost request = new HttpPost("http://www.google.com");
HttpClient = HttpClientBuilder.create().build();
long startTime = System.currentTimeMillis();
HttpResponse baseResponse = internalClient.execute(request);
long duration = System.currentTimeMillis() - startTime;
While duration registers something like 30 seconds, the provider logs shows 1.5 seconds!
So I wonder where is the time being spent? How can this be measured?
Update: An example of the data I would like to have that is possible using cURL: https://blog.josephscott.org/2011/10/14/timing-details-with-curl/
To precisely measure elapsed time in Java use nanoTime() As stated in the docs System.nanoTime():
This method can only be used to measure elapsed time and is not
related to any other notion of system or wall-clock time. The value
returned represents nanoseconds since some fixed but arbitrary origin
time (perhaps in the future, so values may be negative). The same
origin is used by all invocations of this method in an instance of a
Java virtual machine; other virtual machine instances are likely to
use a different origin.
Note that if you need to compare time elapsed between calls in different threads, you must use currentTimeMillis, as nanoTime is not thread safe.
Edit:
See here
The request execution is terminated when the headers are received, body message is later associated with the entity when fully resolved:
EntityUtils.consume(baseResponse.getEntity());
I would like to set arbitrary time in application. Time is downloaded from server in milliseconds format- it should be independent from locale and other system preferences.
But application reacquire thread safety solution, and object like standard not thread safety Calendar object.
Whats is the best way?
Today I use:
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calendar.setTimeInMillis(serverTime);
But is not good way for me beacuse, is't thread safe.
tl;dr
Program have to contain own internal clock fetching time from external server. Clock must be thread-safe.
The time in milliseconds that a Java application uses is
the specified number of milliseconds since the standard base time
known as "the epoch", namely January 1, 1970, 00:00:00 GMT.
This number is based on the GMT time zone. If you need to print it in another time zone you can use any formatting class you want, say SimpleDateFormat. If you need to make the variable that holds it thread safe, just synchronize on it, possibly by wrapping it in a class.
public class TimeInMillis {
private volatile long time;
public void setTime(long time) {this.time = time;}
public time getTime() {return time;}
}
Whenever you need to display it, just get the TimeInMillis object, get the time and create a Calendar object with it. Then use a formatting class to print the time in the format, locale, timezone, you require.
Time is downloaded from server in milliseconds format- it should be independent from locale and other system preferences
That isn't "time". That is a timestamp, meaning a particular time value reported by a particular piece of software at a particular point in time.
Now, if you are trying to say that, in future communications with this server, you want to translate time as reported by the device into the timebase as known by the server, that makes at least a bit of sense. In that case, you compute the delta between the device time when you receive the timestamp and the time value in the timestamp itself. Then, you apply that delta to future times you report back to the server.
Program have to contain own internal clock fetching time from external server
That makes no sense whatsoever.
In this universe, based on our current knowledge of physics, time is continuous and linear. Time does not change only when you are "fetching time from an external server". Again, what you are "fetching... from an external server" is a timestamp, a statement of what the clock on the server thought the time was at the time you made the request. You can use that timestamp for comparison purposes with other timestamps from that server, and you can use that timestamp to compare to the device's current time to determine the difference.
However, you cannot create hardware in Java code, and so you cannot create "internal clock" in Java code. The only clock is the device's clock. As noted earlier, you can translate the device's clock's time to the timebase of the server by applying the aforementioned difference, but the passage of time is still being marked by the device's own clock.
Since the difference is going to be an int or long, you can use AtomicInteger or AtomicLong if you are concerned about multiple threads working with the value at once.
I would just the the time in milli-second with GMT (BTW computers don't support UTC as such)
long serverTime = System.currentTimeMillis(); // millis since 1/1/1970 GMT.
To get/set this in a thread safe manner you can make it volatile
BTW Calender is pretty slow even on a PC. I would avoid using it on a phone.
I am working on google app engine. And I am working on something that requires me to do something if the time-difference between the time sent by the client and the time at server is less than 15 second. The code works perfectly when I try it on the test server (on my own machine). But fails when I the code is deployed on app-engine. I am guess that is probably because if the timezone at server is different, there might be few hours added/subtracted when that occurs.
What I basically do is let the client send his timestamp along with so other data. And when the server subsequently needs to calculate the time difference, I subract server's timestamp from the client's.
If the timezone is different then clearly I will run into problems.
I know that one solution to avoid this timezone fiasco is to let the server timestamp both the initial request and subsequent processing later on, but for my application, it is essential that a timer starts ticking right from when the client makes a request and that if 15 seconds have passed, with respect to the client, then no action be taken by the server.
Since I am the developer of both client side and server side I can show you what I have done.
Sample client side call
new Register().sendToServer(username,location,new TimeStamp(new Date().getTime()));
this is stored in data-store and retrieved a little bit later, if some conditions are met.
Server side sample to find difference
Date date= new Timestamp(new Date().getTime());
Date d1 = (Date) timeStampList[i];
long timedif = Math.abs(d1.getTime() - date.getTime());
if(timedif <= 15000)
do something;
else
do something else;
So basically, my question is how do I normalize the timezone variations ?
thanks
Simpy use absolute unix time: System.currentTimeMillis().
This time is absolute, i.e. no of miliseconds since Jan 1st, 1970, UTC midnight), so you can simply calculate the difference.
As #Diego Basch pointed out if the time difference is in the 30 minutes to full hours magnitude, you should deal with the timezone difference, because your client is not in the same timezone as the server.
You can determine the client timezone in JavaScript with new Date().getTimezoneOffset(). Note: the offset to UTC is returned in minutes.
On the server you should be able to determine the timezone with Calendar.getInstance().getTimeZone().