package com.qyft.ms.app.service; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.io.IOException; import java.time.Instant; /** * 系统相关 */ @Slf4j @Service @RequiredArgsConstructor public class SystemService { /** * 获取当前时间戳(毫秒) */ public long getCurrentEpochMilli() { return Instant.now().toEpochMilli(); } /** * 将系统时区(可选)和系统时间(必选)一起设定 * * @param epochMilli UTC 毫秒时间戳 * @param zone 可选 IANA 时区 ID;若为 null 或空,则不修改时区 */ public void setSystemTime(long epochMilli, String zone) { // 1) 确定要设置的时区:客户端没传就用“Asia/Shanghai” String effectiveZone = (zone != null && !zone.isBlank()) ? zone : "Asia/Shanghai"; // 2) 先修改系统时区(总是执行) runCommand("timedatectl", "set-timezone", effectiveZone); // 3) 再用 date -s @<秒数> 方式设置系统时间 long epochSecond = epochMilli / 1_000; runCommand("date", "-s", "@" + epochSecond); // 4) 将系统时钟写入到硬件时钟(RTC) runCommand("hwclock", "--systohc"); } /** * 辅助:执行系统命令并检查退出码 */ private void runCommand(String... cmd) { try { ProcessBuilder pb = new ProcessBuilder(cmd); pb.inheritIO(); Process p = pb.start(); int exit = p.waitFor(); if (exit != 0) { throw new IllegalStateException( String.format("命令 %s 执行失败,退出码=%d", String.join(" ", cmd), exit) ); } } catch (IOException | InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("执行系统命令失败: " + String.join(" ", cmd), e); } } }