Как установить системное время на Java?
Можно ли изменить системное время в Java?
Он должен работать под управлением Windows и Linux. Я пробовал это с классом Runtime
, но есть проблема с разрешениями.
Вот мой код:
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);
Выход cmd
таков:
date -s "06/01/2011 17:59:01"
Но системное время такое же, как и раньше.
Я установлю время, потому что я пишу NTP-клиент, и там я получаю время от NTP-сервера и установлю его.
7 ответов:
Java не имеет API для этого.
Большинство системных команд для этого требуют прав администратора, поэтому
Runtime
не может помочь, если вы не запустите весь процесс от имени администратора / root или не используетеrunas
/sudo
.В зависимости от того, что вам нужно, вы можете заменить
System.currentTimeMillis()
. Существует два подхода к этому:
Замените все вызовы
System.currentTimeMillis()
вызовом собственного статического метода, который вы можете заменить:public class SysTime { public static SysTime INSTANCE = new SysTime(); public long now() { return System.currentTimeMillis(); } }
Для тестов можно перезаписать экземпляр с помощью что возвращает другой раз. Добавьте дополнительные методы для создания
Date
и подобных объектов.Если не весь код находится под вашим контролем, установите
ClassLoader
, который возвращает другую реализацию дляSystem
. Это гораздо проще, чем вы думаете:@Override public Class<?> loadClass( String name, boolean resolve ) { if ( "java.lang.System".equals( name ) ) { return SystemWithDifferentTime.class; } return super.loadClass( name, resolve ); }
Одним из способов было бы использование собственных команд.
Для Windows требуются две команды (дата и время):
Runtime.getRuntime().exec("cmd /C date " + strDateToSet); // dd-MM-yy Runtime.getRuntime().exec("cmd /C time " + strTimeToSet); // hh:mm:ss
Для linux одна команда обрабатывает как дату, так и время:
Runtime.getRuntime().exec("date -s " + strDateTimeToSet); // MMddhhmm[[yy]yy]
Вы можете установить системное время, только запустив средство командной строки от имени root или Adminstrator. Команды разные, но вы можете сначала проверить ОС и выполнить соответствующую команду для этой ОС.
Вы можете использовать
JNI
для установки системного времени. Это будет работать на Windows. Вам нужно знатьJNI
иC
.Это функция JNI, прототип будет сгенерирован утилитой
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); }
Оболочка Java JNI будет
class TimeSetter { public native void setSystemTime( short hour, short minutes); static { System.loadLibrary("TimeSetter"); } }
И, наконец, использовать его
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); } }
Бывают случаи, когда процесс не запускается с правами администратора, но у него все еще есть разрешения на установку системного времени. Можно использовать Java Native Access для изменения системного времени и иметь все необходимые источники в Java (проще по сравнению с 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 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); } } }
Запустите этот код в модели администратора windows.