3

I'm working with an agent java application and it is installed on several Windows machines in different places of the world. I would like periodically synchronize windows clock (Date and Time). I have already found the native command to set time in windows by java code:

Runtime.getRuntime().exec("cmd /C date " + strDateToSet); // dd-MM-yy
Runtime.getRuntime().exec("cmd /C time " + strTimeToSet); // hh:mm:ss

or to execute

Runtime.getRuntime().exec("cmd /C date " + strDateToSet + "& time " + strTimeToSet);

But the main problem is focalizied on set date, because is possible that the date format on windows machines is not the same for all machines. For example I could have dd-MM-yy for Italian machine and yy-MM-dd for US machine. So if my application set the date with format dd-MM-yy wuold be wrong for US machine.

Knowing that I cant't use NTP (Machines into LAN with Firewall with out rules only protocol HTTPS port 443) how can I set date correctly by java application for all windows machines ? Which is the best solution both semplicity and maintainability ?

Note: Agent java application has already the timestamp to be set on windows machine passed by web service response, therefore is necessary only to do the setDateAndTime

TEST exec date command with format date yyyy-MM-dd on Windows (set wrong date): enter image description here

Stefano
  • 1,439
  • 4
  • 23
  • 38
  • 3
    Why can't you use NTP? Because that is (IMO) the **best** solution for both simplicity and maintainability. – Elliott Frisch Apr 25 '17 at 15:57
  • 3
    Old school but: http://stackoverflow.com/a/17035731/180100 –  Apr 25 '17 at 15:58
  • Possibly: https://docs.oracle.com/javase/7/docs/api/java/text/DateFormat.html#getDateInstance(int) which uses the default locale. – assylias Apr 25 '17 at 15:58
  • Your assumption is that the "date" command in Windows is localized. It's possible that is true, but have you actually verified this is correct? If you aren't using NTP to set the time, then are you expecting the user to set the time? If that is the case, and if you know all your users will run Windows, then why not just start the SetDateTime application? Or why not simply warn them that they need to set the time and let the user figure out how to do that? (BTW, all they must do is right click on clock and select Adjust date/time). – Teto Apr 25 '17 at 16:18
  • First of all answer to Elliot: I can't use NTP because the machines are into LAN with firewall with out rules only port 443 and protocol HTTPS. Teto I thought that the command can be scheduled once a week automatically. – Stefano Apr 25 '17 at 16:46
  • I have not checked assumption yet. I can try. But I have read that setDateAndTime is possible by SNMP (if the service is active on windows) using java library org.snmp4j.smi. – Stefano Apr 25 '17 at 16:56
  • 2
    @Stefano Usual answer for that is to install an NTP server on the LAN. If you cannot modify the firewall rules to allow transit for that server, you can buy a gps module and make it stratum 1. But NTP is (again, in my opinion) the way to go. – Elliott Frisch Apr 25 '17 at 22:49
  • if not from a time server - where do you want to get the correct time from? – Stephan Apr 26 '17 at 12:04
  • @Stephan: correct time arrive from server. Read the Note into question. I have to only set correct timestamp. I think that unique solution for this case is JNA. – Stefano Apr 26 '17 at 15:08
  • @Stefano - You can setup an NTP server on your network. Of course, it needs a time source. We should not reinvent the wheel. – lit Apr 26 '17 at 15:30

1 Answers1

4

I tried to implement the solution with JNA importing kernel32.dll performed the test on Windows 7 machine with timezone UTC+1 (Italy country).

I describe the steps:

1) I imported my maven project the followed dependencies:

<dependency>
        <groupId>net.java.dev.jna</groupId>
        <artifactId>jna-platform</artifactId>
        <version>4.4.0</version>
</dependency>
<dependency>
        <groupId>net.java.dev.jna</groupId>
        <artifactId>jna</artifactId>
        <version>4.3.0</version>
</dependency>

2) I implemented the followed class:

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import com.sun.jna.Native;
import com.sun.jna.platform.win32.WinBase.SYSTEMTIME;
import com.sun.jna.win32.StdCallLibrary;


@Component
@Qualifier("windowsSetSystemTime")
public class WindowsSetSystemTime {

    /**
     * Kernel32 DLL Interface. kernel32.dll uses the __stdcall calling
     * convention (check the function declaration for "WINAPI" or "PASCAL"), so
     * extend StdCallLibrary Most C libraries will just extend
     * com.sun.jna.Library,
     */
    public interface Kernel32 extends StdCallLibrary {

        boolean SetLocalTime(SYSTEMTIME st);

        Kernel32 instance = (Kernel32) Native.loadLibrary("kernel32.dll", Kernel32.class);

    }

    public boolean SetLocalTime(SYSTEMTIME st) {
        return Kernel32.instance.SetLocalTime(st);
    }

    public boolean SetLocalTime(short wYear, short wMonth, short wDay, short wHour, short wMinute, short wSecond) {
        SYSTEMTIME st = new SYSTEMTIME();
        st.wYear = wYear;
        st.wMonth = wMonth;
        st.wDay = wDay;
        st.wHour = wHour;
        st.wMinute = wMinute;
        st.wSecond = wSecond;
        return SetLocalTime(st);
    }
}

3) By the test class I tried to set the followed date and time

public void setTime(){
        System.out.println("START SYNC " + windowsSetSystemTime);

        windowsSetSystemTime.SetLocalTime((short)2017, (short)10,(short) 29,(short) 11,(short) 35,(short) 0);
    }

TEST RESULT: As result in this case I obtained the correct date and time because the function considered daylight winter time saving that enter at 29 October 2017 3:00.

Before test, clock was set:

enter image description here

After test clock set:

enter image description here

I found out the logic SetLocalTime method into Kernel32.dll by Windows dev center documentation at link: SetLocalTime documentation

Windows Dev center REMARKS SetLocalTime:

The system uses UTC internally. Therefore, when you call SetLocalTime, the system uses the current time zone information to perform the conversion, including the daylight saving time setting. Note that the system uses the daylight saving time setting of the current time, not the new time you are setting. Therefore, to ensure the correct result, call SetLocalTime a second time, now that the first call has updated the daylight saving time setting.

Stefano
  • 1,439
  • 4
  • 23
  • 38