如何用Java设置系统时间?

如何用Java设置系统时间?,java,systemtime,Java,Systemtime,可以用Java更改系统时间吗 它应该在Windows和Linux下运行。我已经在中的运行时类中尝试过,但权限有问题 这是我的代码: String cmd="date -s \""+datetime.format(ntp_obj.getDest_Time())+"\""; try { Runtime.getRuntime().exec(cmd); } catch (IOException e1) { // TODO Auto-generated catch block e1.print

可以用Java更改系统时间吗

它应该在Windows和Linux下运行。我已经在中的
运行时
类中尝试过,但权限有问题

这是我的代码:

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服务器获取时间并将其设置

一种方法是使用本机命令

对于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
获取当前时间,并在需要时提供模拟实现来伪造时间。

您只能通过以root或administrator身份运行命令行工具来设置系统时间。命令不同,但您可以先检查操作系统,然后为该操作系统运行相应的命令。

Java没有API来执行此操作

执行此操作的大多数系统命令都需要管理员权限,因此除非您以管理员/root身份运行整个过程,或者使用
runas
/
sudo
,否则
运行时
将帮不上忙

根据需要,您可以更换
System.currentTimeMillis()
。这有两种方法:

  • 将对
    System.currentTimeMillis()
    的所有调用替换为对您自己的静态方法的调用,您可以替换该方法:

    public class SysTime {
        public static SysTime INSTANCE = new SysTime();
    
        public long now() {
            return System.currentTimeMillis();
        }
    }
    
    对于测试,您可以使用其他时间返回的内容覆盖实例。添加更多方法来创建
    Date
    和类似对象

  • 如果不是所有的代码都在您的控制之下,请安装一个
    类加载器
    ,它为
    系统
    返回一个不同的实现。这比你想象的要简单:

    @Override
    public Class<?> loadClass( String name, boolean resolve ) {
        if ( "java.lang.System".equals( name ) ) {
            return SystemWithDifferentTime.class;
        }
    
        return super.loadClass( name, resolve );
    }
    
    @覆盖
    公共类loadClass(字符串名称,布尔解析){
    if(“java.lang.System”.equals(name)){
    返回系统具有不同的time.class;
    }
    返回super.loadClass(名称、解析);
    }
    

  • 您可以使用
    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);   
    }
    
    JavaJNI包装器将是

    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);
        }
    }
    

    在windows管理员模式下运行此代码。

    在某些情况下,进程不使用管理员权限运行,但仍有权限设置系统时间。可以使用来更改系统时间,并在Java中拥有所有必需的源代码(与JNI相比更简单)

    包github.jna;
    导入com.sun.jna.Native;
    导入com.sun.jna.platform.win32.WinBase.SYSTEMTIME;
    导入com.sun.jna.win32.StdCallLibrary;
    /**
    *提供对Windows SetSystemTime本机API调用的访问。
    *该类基于中的示例
    * 
    */
    公共类WindowsSetSystemTime{
    /**
    *内核32 DLL接口。
    *kernel32.dll使用u stdcall调用约定(检查函数
    *声明为“WINAPI”或“PASCAL”),因此扩展StdCallLibrary
    *大多数C库只会扩展com.sun.jna.Library,
    */
    公共接口内核32扩展StdCallLibrary{
    布尔SetLocalTime(SYSTEMTIME st);
    Kernel32实例=(Kernel32)Native.loadLibrary(“Kernel32.dll”,Kernel32.class);
    }
    公共布尔值SetLocalTime(SYSTEMTIME st){
    返回Kernel32.instance.SetLocalTime(st);
    }
    公共布尔值SetLocalTime(短wYear、短wMonth、短wDay、短wHour、短wMinute、短wSecond){
    SYSTEMTIME st=新的SYSTEMTIME();
    圣威耳=威耳;
    st.W月=W月;
    st.wDay=wDay;
    圣呼=呼;
    st.wMinute=wMinute;
    st.wSecond=wSecond;
    返回SetLocalTime(st);
    }       
    }
    
    您可以使用以下代码更改日期或在当前日期中添加日期。它在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天,您可以传递StreExpectedDate的任何日期,这只在windows上起作用

    为什么您需要设置系统时间?还包括当前相关代码和遇到的错误/问题(例如,权限中的“错误”是什么?)@SSZero,因为系统时间不正确/不准确?您需要在Windows上使用单独的时间命令。Runtime.getRuntime().exec(“cmd/C time”+strTimeToSet);//hh:mm:ss安装带有
    java.lang.*
    名称的类加载器是否总是有效?是的,就类加载而言,
    java.lang
    没有什么神奇之处。就JIT和VM而言,它不应该有什么神奇之处——如果你用其他东西替换
    String.class
    ,这应该是可行的,因为类是像其他东西一样加载的。我正在测试第2种方法,得到:java.lang.SecurityException:禁止的包名:java.lang,所以我认为实际上有一些“神奇之处”关于java.lang.@BoneGoat:不,没有。但是你已经安装了
    SecurityManager
    ,这样的事情就不可能再发生了。改为使用
    joda time
    。@Pacerier不确定Mac中是否有不同的命令/util,您可以在Mac上试用terminal@JigarJoshi问题是我没有Mac(在Windows上)btw date只更改日期,我们还需要执行命令time来更改系统时间。@msanjay查找命令来设置时间,我想date应该做itAs
    exec()
    为每个调用派生一个新的进程,我建议对两个windows调用进行如下操作:
    Runtime.getRuntime().exec(“cmd/C date”+strDateToSet+“&time”+strTimeToSet)
    
    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();
            }
        }
    }
    
    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);