Как установить системное время в 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-сервера и устанавливаю его.
Ответы
Ответ 1
У 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();
}
}
Для тестов вы можете перезаписать INSTANCE с чем-то, что возвращает другое время. Добавьте еще несколько методов для создания 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 );
}
Ответ 2
Одним из способов будет использование собственных команд.
для 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]
Обновление через 9 лет
Это не хороший способ установить время системы вместо того, чтобы использовать java.util.Clock
, чтобы получить текущее время и обеспечить ложную реализацию там, где это необходимо, чтобы подделать время.
Ответ 3
Вы можете установить системное время, запустив инструмент командной строки как root или Adminstrator. Команда отличается, но вы можете сначала проверить ОС и запустить соответствующую команду для этой ОС.
Ответ 4
Вы можете использовать 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);
}
}
Ответ 5
Есть случаи, когда процесс не запускается с правами администратора, но у него все еще есть разрешения на установку системного времени. Можно использовать 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);
}
}
Ответ 6
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.
Ответ 7
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();
}
}
}
Ответ 8
Вы можете изменить дату или добавить дату в текущую дату, используя код ниже. Он отлично работает в Windows:
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, 1);
SimpleDateFormat s = new SimpleDateFormat("MM-dd-yyyy");
String strExpectedDate = s.format(new Date(cal.getTimeInMillis()));
Runtime rt = Runtime.getRuntime();
rt.exec("cmd /C date " + strExpectedDate);
В приведенном выше коде я добавил 1 день к текущей дате, вы можете передать любую дату для strExpectedDate, и это будет работать только на окнах