How can I set the System Time in Java?

Is it possible to change the System Time in Java?

It should run under Windows and Linux. I've tried it with the Runtime Class in but there is a problem with the permissions.

This is my code:

String cmd="date -s \""+datetime.format(ntp_obj.getDest_Time())+"\"";
try {
    Runtime.getRuntime().exec(cmd);
} catch (IOException e1) {
// TODO Auto-generated catch block
  e1.printStackTrace();
}
System.out.println(cmd);

The output of cmd is:

date -s "06/01/2011 17:59:01"

But the System time is the same as before.

I will set the time because I am writing an NTP-Client and there I get the time from a NTP-Server and will set it.


Solution 1:

Java doesn't have an API to do this.

Most system commands to do it require admin rights, so Runtime can't help unless you run the whole process as administrator/root or you use runas/sudo.

Depending on what you need, you can replace System.currentTimeMillis(). There are two approaches to this:

  1. Replace all calls to System.currentTimeMillis() with a call to a static method of your own which you can replace:

    public class SysTime {
        public static SysTime INSTANCE = new SysTime();
    
        public long now() {
            return System.currentTimeMillis();
        }
    }
    

    For tests, you can overwrite INSTANCE with something that returns other times. Add more methods to create Date and similar objects.

  2. If not all code is under your control, install a ClassLoader which returns a different implementation for System. This is more simple than you'd think:

    @Override
    public Class<?> loadClass( String name, boolean resolve ) {
        if ( "java.lang.System".equals( name ) ) {
            return SystemWithDifferentTime.class;
        }
    
        return super.loadClass( name, resolve );
    }
    

Solution 2:

One way would be using native commands.

for Windows, two commands (date and time) are required:

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

for linux, a single command handles both date and time:

Runtime.getRuntime().exec("date -s " + strDateTimeToSet); // MMddhhmm[[yy]yy]

Update after 9 year

This is not a good way to set the time of system instead of that use java.util.Clock to get the current time and provide mock implementation wherever needed to fake out the time.

Solution 3:

You can only set the system time by running a command line tool as root or Adminstrator. The command are different but you can check the OS first and run the appropriate command for that OS.

Solution 4:

You can use JNI for setting the system time. This would work on Windows. You need to know JNI and C.

This is the JNI function, the prototype will be generated by the javah utility

JNIEXPORT void JNICALL Java_TimeSetter_setSystemTime
  (JNIEnv *env, jobject obj, jshort hour, jshort minutes) {

    SYSTEMTIME st;
    GetLocalTime(&st);  
    st.wHour = hour;      
    st.wMinute = minutes;  
    SetLocalTime(&st);   
}

The Java JNI wrapper would be

class TimeSetter {

    public native void setSystemTime( short hour, short minutes);

    static {
        System.loadLibrary("TimeSetter");
    }
}

And finally, to use it

public class JNITimeSetter {

    public static void main(String[] args) {

        short hour = 8;
        short minutes = 30;

        // Set the system at 8h 30m

        TimeSetter ts = new TimeSetter();
        ts.setSystemTime(hour, minutes);
    }
}