Est-il possible de changer l'heure du système en Java?
Il devrait fonctionner sous Windows et Linux. Je l'ai essayé avec la classe Runtime
dans, mais il y a un problème avec les autorisations.
Ceci est mon 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);
La sortie de cmd
est:
date -s "06/01/2011 17:59:01"
Mais l'heure système est la même qu'avant.
Je vais régler l'heure car je suis en train d'écrire un client NTP et j'obtiens l'heure d'un serveur NTP et je vais la régler.
Java n'a pas d'API pour faire cela.
La plupart des commandes système nécessaires à cette opération nécessitent des droits d'administrateur. Par conséquent, Runtime
ne peut vous aider que si vous exécutez l'ensemble du processus en tant qu'administrateur/root ou si vous utilisez runas
/Sudo
.
En fonction de vos besoins, vous pouvez remplacer System.currentTimeMillis()
. Il y a deux approches à cela:
Remplacez tous les appels à System.currentTimeMillis()
par un appel à une méthode statique que vous pouvez remplacer:
public class SysTime {
public static SysTime INSTANCE = new SysTime();
public long now() {
return System.currentTimeMillis();
}
}
Pour les tests, vous pouvez écraser INSTANCE avec quelque chose qui renvoie d'autres heures. Ajoutez d'autres méthodes pour créer des objets Date
et similaires.
Si tout le code n'est pas sous votre contrôle, installez une ClassLoader
qui renvoie une implémentation différente pour System
. C'est plus simple que vous ne le pensez:
@Override
public Class<?> loadClass( String name, boolean resolve ) {
if ( "Java.lang.System".equals( name ) ) {
return SystemWithDifferentTime.class;
}
return super.loadClass( name, resolve );
}
Une façon serait d'utiliser des commandes natives.
pour Windows, deux commandes (date et heure) sont requises:
Runtime.getRuntime().exec("cmd /C date " + strDateToSet); // dd-MM-yy
Runtime.getRuntime().exec("cmd /C time " + strTimeToSet); // hh:mm:ss
pour linux, une seule commande gère à la fois la date et l'heure:
Runtime.getRuntime().exec("date -s " + strDateTimeToSet); // MMddhhmm[[yy]yy]
Vous ne pouvez définir l'heure système qu'en exécutant un outil de ligne de commande en tant qu'utilisateur root ou administrateur. La commande est différente, mais vous pouvez d'abord vérifier le système d'exploitation et exécuter la commande appropriée pour ce système d'exploitation.
Vous pouvez utiliser JNI
pour régler l’heure du système. Cela fonctionnerait sur Windows. Vous devez connaître JNI
et C
.
C'est la fonction JNI, le prototype sera généré par l'utilitaire javah
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);
}
Le wrapper Java JNI serait
class TimeSetter {
public native void setSystemTime( short hour, short minutes);
static {
System.loadLibrary("TimeSetter");
}
}
Et enfin, l'utiliser
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);
}
}
Dans certains cas, le processus ne s'exécute pas avec des droits d'administrateur, mais il dispose toujours des autorisations nécessaires pour définir l'heure du système. Il est possible d’utiliser Java Native Access pour modifier l’heure du système et disposer de toutes les sources requises en Java (plus simple que JNI).
package github.jna;
import com.Sun.jna.Native;
import com.Sun.jna.platform.win32.WinBase.SYSTEMTIME;
import com.Sun.jna.win32.StdCallLibrary;
/**
* Provides access to the Windows SetSystemTime native API call.
* This class is based on examples found in
* <a href="https://github.com/twall/jna/blob/master/www/GettingStarted.md">JNA Getting Started</a>
*/
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);
}
}
package com.test;
public class Exec {
public static void main(String[] args) {
try {
String[] cmd = {"/bin/bash","-c","echo yourPassword | Sudo -S date --set='2017-05-13 21:59:10'"};
Runtime.getRuntime().exec(cmd);
} catch (Exception e) {
e.printStackTrace();
}
}
}
package myTestProject;
import Java.text.DateFormat;
import Java.text.SimpleDateFormat;
import Java.util.Date;
public class LocalTimeChangeTest {
private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) {
try {
String value = "2014-12-12 00:26:14";
Date date = dateFormat.parse(value);
value = dateFormat.format(date);
final Process dateProcess = Runtime.getRuntime().exec("cmd /c date "+value.substring(0, value.lastIndexOf(' ')));
dateProcess.waitFor();
dateProcess.exitValue();
final Process timeProcess = Runtime.getRuntime().exec("cmd /c time "+value.substring(value.lastIndexOf(' ')+1));
timeProcess.waitFor();
timeProcess.exitValue();
} catch (Exception exception) {
throw new RuntimeException(exception);
}
}
}
Exécutez ce code sous le modèle d'administrateur Windows.