4 changed files with 139 additions and 3 deletions
-
30src/main/java/com/qyft/ms/app/controller/SystemController.java
-
21src/main/java/com/qyft/ms/app/model/dto/TimeSetDTO.java
-
22src/main/java/com/qyft/ms/app/model/vo/TimeResponseVO.java
-
69src/main/java/com/qyft/ms/app/service/SystemService.java
@ -0,0 +1,21 @@ |
|||||
|
package com.qyft.ms.app.model.dto; |
||||
|
|
||||
|
import io.swagger.v3.oas.annotations.media.Schema; |
||||
|
import jakarta.validation.constraints.NotNull; |
||||
|
import lombok.Data; |
||||
|
|
||||
|
@Data |
||||
|
public class TimeSetDTO { |
||||
|
/** |
||||
|
* 要设置的时间戳(毫秒),UTC 纪元毫秒数 |
||||
|
*/ |
||||
|
@NotNull |
||||
|
@Schema(description = "要设置的时间戳(毫秒),UTC 纪元毫秒数") |
||||
|
private Long epochMilli; |
||||
|
|
||||
|
/** |
||||
|
* 可选:要设置的系统时区,如 "Asia/Tokyo"、"Europe/London" |
||||
|
*/ |
||||
|
@Schema(description = "可选:要设置的系统时区,如 \"Asia/Tokyo\"、\"Europe/London\"") |
||||
|
private String zone; |
||||
|
} |
@ -0,0 +1,22 @@ |
|||||
|
package com.qyft.ms.app.model.vo; |
||||
|
|
||||
|
import io.swagger.v3.oas.annotations.media.Schema; |
||||
|
import lombok.Data; |
||||
|
import lombok.EqualsAndHashCode; |
||||
|
|
||||
|
import java.time.ZoneId; |
||||
|
|
||||
|
@Data |
||||
|
public class TimeResponseVO { |
||||
|
|
||||
|
@Schema(description = "当前系统时间的 UTC 毫秒时间戳") |
||||
|
private long epochMilli; |
||||
|
|
||||
|
@Schema(description = "时区") |
||||
|
private String zone; |
||||
|
|
||||
|
public TimeResponseVO(long epochMilli, ZoneId zoneId) { |
||||
|
this.epochMilli = epochMilli; |
||||
|
this.zone = zoneId.getId(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,69 @@ |
|||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue