Подтвердить что ты не робот

Как установить системное время в 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-сервера и устанавливаю его.

4b9b3361

Ответ 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, и это будет работать только на окнах