I am trying to build a sample application which will show a proof of concept for synchronizing the time with an RFC 868 compliant time server.
So far, using the Java Socket API, I am able to connect and query the server and do get the response from the server, but it is not in human readable format.
The response I get is: �)6 I think the response is coming in binary format (not sure though). RFC 868 says that Send the time as a 32 bit binary number.
My questions are:
How do I parse this response?
Apart from this approach of mine, I'd like to know if there is any other recommended approach which I should take to achieve this.
Thanks in advance.
1) How do I parse this response?
Check out the source code of TimeTCPClient from Apache Commons Net library:
public long getTime() throws IOException {
DataInputStream input;
input = new DataInputStream(_input_);
return (input.readInt() & 0xffffffffL);
}
public Date getDate() throws IOException {
return new Date((getTime() - SECONDS_1900_TO_1970)*1000L);
}
2) Apart from this approach of mine, I'd like to know if there is any other recommended approach which I should take to achieve this.
Use Apache Commons Net Library, check out the API of TimeTCPClient.
Apache Commons Net home page, hope this helps.
As stated in the RFC this is the seconds since 1900-01-01T00:00:00. For Java convert it to a Long,change the base date to 1970-01-01T00:00:00, and multiply by 1000 to get the date. Then you can create a new Date using this value.
Wrap your socket input stream to a DataInputStream and read an into rfsOffset (I used a constant). Then you can do something like:
int rfcOffset = -752253627; // Fri Apr 06 11:00:32 EDT 2012
// Current offsets will be negative convert to long positive value
long offsetSecs = rfcOffset + 4294967296L;
System.out.println(offsetSecs);
// Adjust time base from 1900 to 1970 and convert to millis
long offsetMillis = ( offsetSecs - 2208988800L)* 1000L;
System.out.println(offsetMillis);
Date rfcDate = new Date(offsetMillis);
System.out.println(rfcDate.toString());
Note: this only works until 2036 and time will be off by some number of milliseconds.
EDIT: RFC 868 is an old protocol and is no longer considered a good time source for synchronization. A good time source will us NTP and will return the correct second. It may be off a few milliseconds, but is normally accurate withing 10 milliseconds. Many hardware clocks drift significantly, and I have seen significant drift from systems with inaccurate clocks (even with NTP running(). NTP will correct a drifting clock, but needs a few minutes to determine the required shift.
EDIT2: While RFC 868 is old, it may be good enough to set the time on a cell phone to the nearest second without requiring a background process. This shouldn't be necessary if your cell phone can sync to a signal sent by your provider.
Related
I'm aware that you can use DateUtils.formatElapsedTime(seconds) to convert a number of seconds into a String with the format HH:MM:SS. But are there any utility functions that let me perform the same conversion but without the seconds?
For example, I want to convert 3665 seconds into 1:01, even though it's exactly 1:01:05. In other words, simply dropping the seconds part.
Would strongly prefer an answer that points to a utility function (if one exists) rather than a bunch of home rolled algorithms.
Use Apache Commons Lang
You could use utility class DateFormatUtils of Apache's well known utility library Commons Lang, combined with TimeUnit to convert from seconds to milliseconds:
static String format(long durationSeconds) {
long durationMillis = TimeUnit.SECONDS.toMillis(durationSeconds);
// Commons lang:
return DurationFormatUtils.formatDuration(durationMillis, "HH:mm");
}
Use with input 3665 it prints:
01:01
Personally I'd prefer to use Java8 or Java9 standard library (see the other answers) rather than introducing a dependency just to make it 1 method call.
MadProgrammer has already provided a good Java 8 answer (which will work in Java 6 and 7 too when you use the ThreeTen Backport). In Java 9 still a bit more of the calculation can be done in the library:
int seconds = 3665;
Duration dur = Duration.ofSeconds(seconds);
String formatted = String.format("%d:%02d", dur.toHours(), dur.toMinutesPart());
System.out.println(formatted);
Output:
1:01
The toMinutesPart method and other toXxxPart methods were introduced in Java 9.
Based on the available information, you seem to be wanting to format a duration based value. Lucky for us, since Java 8, there is now a new java.time API which includes a Duration class.
Unfortunately, it doesn't (at least the last time checked) support a formatter for it.
However, you could easily roll your own...
protected static String format(Duration duration) {
long hours = duration.toHours();
long mins = duration.minusHours(hours).toMinutes();
return String.format("%02d:%02d", hours, mins);
}
Which when used with something like...
System.out.println(format(Duration.ofSeconds(3665)));
prints out 01:01.
Now I know you'd "prefer" utility methods, but you're unlikely to find something that fits your "every" need and this at least gives you a starting point. Besides, you could always make a pull request ;)
In Java I am getting a timestamp this way:
Date date= new java.util.Date();
return (new Timestamp(date.getTime())).toString();
Output is for example:
Start - 2015-02-16 13:59:41.427
Then I write a packet to a socket.
However, in Wireshark, the first packet is dated as follows:
62 2015-02-16 13:59:41.421115000 ...
What???
Ok, I don't want someone to tell me the timestamps are off. Is there a way to change the Java code to make it produce timesstamp that are more in line with Wireshark?
Thanks
EDIT: Code Requested
System.err.println("Start - "+currentTimestamp());
int sent = socketChannelOut.write(data);
I suspect this is simply down to the to the accuracy of how your system measures time. To quote from the java doc:
"Returns the current time in milliseconds. Note that while the unit of
time of the return value is a millisecond, the granularity of the
value depends on the underlying operating system and may be larger.
For example, many operating systems measure time in units of tens of
milliseconds."
Since the discrepancy you are seeing is 0.005885s and this is less than 10ms I do not think there is an expectation that a comparison with another process measuring time will be accurate to less than 10ms granularity. Which is to say this time 41.427 that you got from Java is really 41.427 +/-10ms
I'm an objective-c beginner and I was assigned to create an iPhone app for our client. I have some background with Java but almost no experience in this objective-c and this is my first time to developping a complete application...
Anyway, I'm currently stack at several problems. One of those problem is that I need to send an integer value for PHP's date function from my iOS app. I've been searching around for the solution, but all of them are dealing with opposite ways (int to NSDate), not NSDate to integer value.
I tried solutions like answered here
but it's obvious it returns double, not an integer...
Or this
but this couldn't get the System time.
I know I could get current system's NSDate with:
NSDate *theDay = [NSDate dateWithTimeIntervalSinceNow:[[NSTimeZone systemTimeZone] secondsFromGMT]];
But I could not figure out how to convert this to an integer (or long) value.
I just need to get the same value as we can get in Java with System.currentTimeMillis().
Also, this is my first time to ask questions here in stackoverflow. So please let me know if there's anything I should do/not to do when posting questions here, etc.
Thank you.
To get the current date, you should use this:
NSDate *theDate = [NSDate date];
To get it in seconds since January 1st, 1970, as a double, you would use:
NSTimeInterval seconds = [[NSDate date] timeIntervalSince1970];
To get it in ms, simply multiply the previous value by 1000 and let the compiler cast it into an integer without needing any additional code:
long long milliseconds = [[NSDate date] timeIntervalSince1970] * 1000;
And as #HotLicks points out, while System.currentTimeMillis() is in GMT, if you need the local time, you could use:
long long milliseconds = ([[NSDate date] timeIntervalSince1970]
+ [[NSTimeZone defaultTimeZone] secondsFromGMT]) * 1000;
(I think that most web services will want GMT though.)
I'm trynig to write a proto file that has a Date field which is not defined as a type into Protocol buffer.
I have read the following post but I couldn't figure out a proper solution that suits me :
What the best ways to use decimals and datetimes with protocol buffers?.
I'm trying to convert the proto file to a java .
My answer in the linked post relates mainly to protobuf-net; however, since you are coming at this from java I would recommend: keep it simple.
For dates, I would suggest just using the time (perhaps milliseconds) into an epoch (1 Jan 1970 is traditional). For times, just the size in that same unit (milliseconds etc). For decimal, maybe use fixed point simply by scaling - so maybe treat 1.05 as the long 1050 and assert always exactly 3dp (hence fixed point).
This is simple and pragmatic, and covers most common scenarios without making things complicated.
I'm not sold on this idea, but I'm really not sold on the idea of storing dates (which aren't instants in time) as a timestamp, so here's my suggestion.
Convert your date into a human-readable integer (e.g. 2014-11-3 becomes 20141103) and store this integer value. It contains exactly the data you need, is simple to create and parse, and takes up minimal space. Additionally, it is ordered and has a one-to-one mapping of dates to valid values (granted, invalid numbers are possible, such as 20149999, but these are easy to detect). In contrast, there are approximately 86400 valid timestamps that represent each day.
NB: There is a discussion on DBA SE criticizing this method of date storage, but in that context a specialized date type exists, which obviously isn't the case here.
I am working with AD via LDAP (using Spring LDAP) and I ran into a odd problem while working with Integer8/LargeInteger being used as timestamps which are outlined here. Namely, my attempts to write to fields of that type have resulted in...
Malformed 'field name here' attribute value
I've tried putting Longs and Strings in hopes that the underlying implementation would do any needed conversions but no luck. Here is how I am doing my math...
/* AD Keeps track of time in 100 NS intervals (UTC) since Jan 1st 1601 */
long winEpocMS = new GregorianCalendar(1601, Calendar.JANUARY, 1).getTimeInMillis();
long nowMS = System.currentTimeMillis();
long winTime100NS = (nowMS - winEpocMS) * 10000;
Is there a easy/elegant way to pack this data correctly? Are there any Java libs prebuilt to handle reading/writing these rather odd time values?
Bonus points to anyone that can explain why we need a 64bit timestamp at the 100NS resolution.
Ok here's the breakdown...
/* time since Jan 1st 1601 00:00:00 UTC */
final long WIN_EPOC_MS = 11644473600000L;
final long now_ms = System.currentTimeMillis();
final long now_win_ns = (now_ms + WIN_EPOC_MS) * 10000L;
The reverse should be obvious from the above code. If you want to double check the convertions use w32tm. For example, the following shows that we have the right convertion time to the Unix epoc (note that I am in CST)
w32tm /ntte 116444736000000000
134774 00:00:00.0000000 - 12/31/1969
06:00:00 PM (local time)
Finally, when working with AD make sure the field accepts any value. Some fields take "-1" to mean "now" and "0" may have special meaning. Also, in some cases it seems to matter if the time attribute modification is bundled with other attribute modifications (such as pwdLastSet and unicodePwd).
One last note, I would avoid GregorianCalendar unless you know you have your timezones right (it's easy to mess up).
I not know any Java library that handle the time with that Microsoft-specific format (100 nanosecond intervals since 1601). I think this ways is correct.
You can define winEpocMS as a constant and use:
long winTime100NS = (System.currentTimeMillis() - winEpocMS) * 10000L;
Why we need 64bit timestamp is simple. With 32bit you got 2^32 values (roughly 4,000,000,000), enough to handle seconds since 1970 until 2038 (know as the 2000-year effect on Unix). If you need microseconds or 100 nanoseconds precision, you use bigger values that have to be managed as 64 bit numbers. Java uses milliseconds since 1970 to represent dates and requires long type that is a signed 64 bit number.