I did it with shortcuts. Shortcut has link to cmd
with commands, changing time or synchronize time with server time. As changing system settings shortcut should be called with admin permission there is a method automatically setting shortcut flag Run as administrator
. To be sure that synchronization was succesfull there is a method safeSynchronize
changing time to fake time and only after that ask the server time. For me it works perfectly.
package system;
import mslinks.ShellLink;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.time.DateUtils;
import java.io.*;
import java.nio.file.Files;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
public class TimeSynchronizer {
Random random = new Random();
private int WAIT_LAG = 1000;
private DateFormat dateFormat = new SimpleDateFormat("dd-MM-yy");
private DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
public void synchronize() throws IOException, InterruptedException {
File file = getFile();
makeShortcut(file, "/c net start w32time");
callShortcut(file);
makeShortcut(file, "/c w32tm /resync");
callShortcut(file);
if (file.exists()) file.delete();
}
public void safeSynchronize() throws IOException, InterruptedException {
Calendar rightNow = Calendar.getInstance();
int minute = rightNow.get(Calendar.MINUTE);
boolean isForward = minute < 30;
Date date = DateUtils.addMinutes(Date.from(Instant.now()), 10 * (isForward ? 1 : -1));
setTime(date);
synchronize();
}
public void setTime(Date date) throws IOException, InterruptedException {
setTime(date, false);
}
public void setTime(Date date, boolean withDate) throws IOException, InterruptedException {
File file = getFile();
if (withDate) {
makeShortcut(file, "/c date " + dateFormat.format(date));
callShortcut(file);
}
makeShortcut(file, "/c time " + timeFormat.format(date));
callShortcut(file);
if (file.exists()) file.delete();
}
private void callShortcut(File file) throws IOException, InterruptedException {
Process process = Runtime.getRuntime().exec(
getSystem32Path() + "\\cmd.exe /c start /wait \"\" \"" + file.getAbsolutePath() + "\""
);
process.waitFor();
process.exitValue();
}
private String getSystem32Path() {
return System.getenv("SystemRoot") + "\\system32";
}
private File getFile() {
return new File(random.nextInt() + "shortcut.lnk");
}
private void makeShortcut(File file, String command) throws IOException, InterruptedException {
String system32Path = getSystem32Path();
ShellLink s = new ShellLink();
s.setTarget(system32Path + "\\cmd.exe");
s.setCMDArgs(command);
s.saveTo(file.getAbsolutePath());
Thread.sleep(WAIT_LAG);
setRunAsAdmin(file);
}
private void setRunAsAdmin(File file) throws IOException {
byte[] fileContent = Files.readAllBytes(file.toPath());
fileContent[21] = (char)32;
FileUtils.writeByteArrayToFile(file, fileContent);
}
}