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サーバーから時刻を取得して設定します。
Javaにはこれを行うAPIがありません。
それを行うほとんどのシステムコマンドには管理者権限が必要なため、プロセス全体を管理者/ルートとして実行するか、Runtime
/runas
を使用しない限り、Sudo
は役に立ちません。
必要なものに応じて、System.currentTimeMillis()
を置き換えることができます。これには2つのアプローチがあります。
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 );
}
1つの方法は、ネイティブコマンドを使用することです。
windowsの場合、2つのコマンド(日付と時刻)が必要です。
Runtime.getRuntime().exec("cmd /C date " + strDateToSet); // dd-MM-yy
Runtime.getRuntime().exec("cmd /C time " + strTimeToSet); // hh:mm:ss
linuxの場合、1つのコマンドで日付と時刻の両方を処理します。
Runtime.getRuntime().exec("date -s " + strDateTimeToSet); // MMddhhmm[[yy]yy]
9年後に更新
これはJava.util.Clock
を使用して現在の時刻を取得し、時刻を偽造する必要がある場所にモック実装を提供する代わりに、システムの時刻を設定する良い方法ではありません。
RootまたはAdminstratorとしてコマンドラインツールを実行することによってのみ、システム時刻を設定できます。コマンドは異なりますが、最初にOSを確認し、そのOSに適切なコマンドを実行できます。
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 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);
}
}
}
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には任意の日付を渡すことができ、これはWindowsでのみ機能します