mirror of
https://github.com/nsnail/dot.git
synced 2025-06-18 05:23:21 +08:00
..
This commit is contained in:
parent
4ab2af5ca3
commit
507b0aec5b
117
src/Lang/Strings.Designer.cs
generated
117
src/Lang/Strings.Designer.cs
generated
@ -122,6 +122,96 @@ namespace Dot.Lang {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 连接NTP服务器: {0} <{1}> ... .
|
||||
/// </summary>
|
||||
public static string Main_GetUtc_ {
|
||||
get {
|
||||
return ResourceManager.GetString("Main_GetUtc_", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} ms.
|
||||
/// </summary>
|
||||
public static string Main_GetUtc__0_us {
|
||||
get {
|
||||
return ResourceManager.GetString("Main_GetUtc__0_us", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 发送请求... .
|
||||
/// </summary>
|
||||
public static string Main_GetUtc_sdf {
|
||||
get {
|
||||
return ResourceManager.GetString("Main_GetUtc_sdf", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 接收数据... .
|
||||
/// </summary>
|
||||
public static string Main_GetUtc_接收请求___ {
|
||||
get {
|
||||
return ResourceManager.GetString("Main_GetUtc_接收请求___", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to NTP服务器时间: {0}.
|
||||
/// </summary>
|
||||
public static string Main_Run_NTP服务器时间___0_ {
|
||||
get {
|
||||
return ResourceManager.GetString("Main_Run_NTP服务器时间___0_", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 按"y"同步系统时钟, 其它按键退出程序.
|
||||
/// </summary>
|
||||
public static string Main_Run_SyncClock {
|
||||
get {
|
||||
return ResourceManager.GetString("Main_Run_SyncClock", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 同步完成, 开始复检....
|
||||
/// </summary>
|
||||
public static string Main_Run_SyncDone {
|
||||
get {
|
||||
return ResourceManager.GetString("Main_Run_SyncDone", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 本地时钟快: {0} ms.
|
||||
/// </summary>
|
||||
public static string Main_Run_时差___0__ms {
|
||||
get {
|
||||
return ResourceManager.GetString("Main_Run_时差___0__ms", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 本地时钟慢: {0} ms.
|
||||
/// </summary>
|
||||
public static string Main_Run_时差___1__ms {
|
||||
get {
|
||||
return ResourceManager.GetString("Main_Run_时差___1__ms", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 本地时间: {0}.
|
||||
/// </summary>
|
||||
public static string Main_Run_本地时间___0_ {
|
||||
get {
|
||||
return ResourceManager.GetString("Main_Run_本地时间___0_", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 没有需要处理的文件.
|
||||
/// </summary>
|
||||
@ -131,6 +221,24 @@ namespace Dot.Lang {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 所有服务均不可用.
|
||||
/// </summary>
|
||||
public static string NoService {
|
||||
get {
|
||||
return ResourceManager.GetString("NoService", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OK.
|
||||
/// </summary>
|
||||
public static string OK {
|
||||
get {
|
||||
return ResourceManager.GetString("OK", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 指定的路径“{0}”不存在.
|
||||
/// </summary>
|
||||
@ -230,6 +338,15 @@ namespace Dot.Lang {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 超时.
|
||||
/// </summary>
|
||||
public static string Timeout {
|
||||
get {
|
||||
return ResourceManager.GetString("Timeout", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 移除文件的uf8 bom.
|
||||
/// </summary>
|
||||
|
@ -91,4 +91,43 @@
|
||||
<data name="NoFileToBeProcessed" xml:space="preserve">
|
||||
<value>没有需要处理的文件</value>
|
||||
</data>
|
||||
<data name="Main_GetUtc_" xml:space="preserve">
|
||||
<value>连接NTP服务器: {0} <{1}> ... </value>
|
||||
</data>
|
||||
<data name="Main_GetUtc__0_us" xml:space="preserve">
|
||||
<value>{0} ms</value>
|
||||
</data>
|
||||
<data name="Main_GetUtc_sdf" xml:space="preserve">
|
||||
<value>发送请求... </value>
|
||||
</data>
|
||||
<data name="Main_GetUtc_接收请求___" xml:space="preserve">
|
||||
<value>接收数据... </value>
|
||||
</data>
|
||||
<data name="Timeout" xml:space="preserve">
|
||||
<value>超时</value>
|
||||
</data>
|
||||
<data name="OK" xml:space="preserve">
|
||||
<value>OK</value>
|
||||
</data>
|
||||
<data name="NoService" xml:space="preserve">
|
||||
<value>所有服务均不可用</value>
|
||||
</data>
|
||||
<data name="Main_Run_NTP服务器时间___0_" xml:space="preserve">
|
||||
<value>NTP服务器时间: {0}</value>
|
||||
</data>
|
||||
<data name="Main_Run_本地时间___0_" xml:space="preserve">
|
||||
<value>本地时间: {0}</value>
|
||||
</data>
|
||||
<data name="Main_Run_时差___0__ms" xml:space="preserve">
|
||||
<value>本地时钟快: {0} ms</value>
|
||||
</data>
|
||||
<data name="Main_Run_时差___1__ms" xml:space="preserve">
|
||||
<value>本地时钟慢: {0} ms</value>
|
||||
</data>
|
||||
<data name="Main_Run_SyncClock" xml:space="preserve">
|
||||
<value>按"y"同步系统时钟, 其它按键退出程序</value>
|
||||
</data>
|
||||
<data name="Main_Run_SyncDone" xml:space="preserve">
|
||||
<value>同步完成, 开始复检...</value>
|
||||
</data>
|
||||
</root>
|
180
src/Time/Main.cs
Normal file
180
src/Time/Main.cs
Normal file
@ -0,0 +1,180 @@
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Dot.Time;
|
||||
|
||||
public sealed class Main : Tool<Option>
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public ref struct _SYSTEMTIME
|
||||
{
|
||||
[FieldOffset(6)] public ushort wDay;
|
||||
[FieldOffset(4)] public ushort wDayOfWeek;
|
||||
[FieldOffset(8)] public ushort wHour;
|
||||
[FieldOffset(14)] public ushort wMilliseconds;
|
||||
[FieldOffset(10)] public ushort wMinute;
|
||||
[FieldOffset(2)] public ushort wMonth;
|
||||
[FieldOffset(12)] public ushort wSecond;
|
||||
[FieldOffset(0)] public ushort wYear;
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, string> _serverList = new() {
|
||||
{ "ntp.ntsc.ac.cn", "国家授时中心 NTP 服务器" }
|
||||
, { "cn.ntp.org.cn", "中国 NTP 快速授时服务" }
|
||||
, { "edu.ntp.org.cn", "中国 NTP 快速授时服务" }
|
||||
, { "cn.pool.ntp.org", "国际 NTP 快速授时服务" }
|
||||
, { "time.pool.aliyun.com", "阿里云公共 NTP 服务器" }
|
||||
, { "time1.aliyun.com", "阿里云公共 NTP 服务器" }
|
||||
, { "time2.aliyun.com", "阿里云公共 NTP 服务器" }
|
||||
, { "time3.aliyun.com", "阿里云公共 NTP 服务器" }
|
||||
, { "time4.aliyun.com", "阿里云公共 NTP 服务器" }
|
||||
, { "time5.aliyun.com", "阿里云公共 NTP 服务器" }
|
||||
, { "time6.aliyun.com", "阿里云公共 NTP 服务器" }
|
||||
, { "time7.aliyun.com", "阿里云公共 NTP 服务器" }
|
||||
, { "time1.cloud.tencent.com", "腾讯云公共 NTP 服务器" }
|
||||
, { "time2.cloud.tencent.com", "腾讯云公共 NTP 服务器" }
|
||||
, { "time3.cloud.tencent.com", "腾讯云公共 NTP 服务器" }
|
||||
, { "time4.cloud.tencent.com", "腾讯云公共 NTP 服务器" }
|
||||
, { "time5.cloud.tencent.com", "腾讯云公共 NTP 服务器" }
|
||||
, { "ntp.sjtu.edu.cn", "教育网(高校自建)" }
|
||||
, { "ntp.neu.edu.cn", "教育网(高校自建)" }
|
||||
, { "ntp.bupt.edu.cn", "教育网(高校自建)" }
|
||||
, { "ntp.shu.edu.cn", "教育网(高校自建)" }
|
||||
, { "pool.ntp.org", "国际 NTP 快速授时服务" }
|
||||
, { "0.pool.ntp.org", "国际 NTP 快速授时服务" }
|
||||
, { "1.pool.ntp.org", "国际 NTP 快速授时服务" }
|
||||
, { "2.pool.ntp.org", "国际 NTP 快速授时服务" }
|
||||
, { "3.pool.ntp.org", "国际 NTP 快速授时服务" }
|
||||
, { "asia.pool.ntp.org", "国际 NTP 快速授时服务" }
|
||||
, { "time1.google.com", "谷歌公共 NTP 服务器" }
|
||||
, { "time2.google.com", "谷歌公共 NTP 服务器" }
|
||||
, { "time3.google.com", "谷歌公共 NTP 服务器" }
|
||||
, { "time4.google.com", "谷歌公共 NTP 服务器" }
|
||||
, { "time.apple.com", "苹果公司公共 NTP 服务器" }
|
||||
, { "time1.apple.com", "苹果公司公共 NTP 服务器" }
|
||||
, { "time2.apple.com", "苹果公司公共 NTP 服务器" }
|
||||
, { "time3.apple.com", "苹果公司公共 NTP 服务器" }
|
||||
, { "time4.apple.com", "苹果公司公共 NTP 服务器" }
|
||||
, { "time5.apple.com", "苹果公司公共 NTP 服务器" }
|
||||
, { "time6.apple.com", "苹果公司公共 NTP 服务器" }
|
||||
, { "time7.apple.com", "苹果公司公共 NTP 服务器" }
|
||||
, { "time.windows.com", "微软 Windows NTP 服务器" }
|
||||
, { "time.nist.gov", "美国标准技术研究院 NTP 服务器" }
|
||||
, { "time-nw.nist.gov", "美国标准技术研究院 NTP 服务器" }
|
||||
, { "time-a.nist.gov", "美国标准技术研究院 NTP 服务器" }
|
||||
, { "time-b.nist.gov", "美国标准技术研究院 NTP 服务器" }
|
||||
, { "stdtime.gov.hk", "香港天文台公共 NTP 服务器" }
|
||||
};
|
||||
|
||||
public Main(Option opt) : base(opt) { }
|
||||
|
||||
|
||||
private TimeSpan GetNtpOffset()
|
||||
{
|
||||
Span<byte> ntpData = stackalloc byte[48];
|
||||
TimeSpan ts;
|
||||
ntpData[0] = 0x1B;
|
||||
foreach (var server in _serverList) {
|
||||
Console.Write(Strings.Main_GetUtc_, server.Key, server.Value);
|
||||
|
||||
using var socket
|
||||
= new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) { ReceiveTimeout = 3000 };
|
||||
|
||||
try {
|
||||
socket.Connect(_serverList.First().Key, 123);
|
||||
Console.WriteLine(Strings.OK);
|
||||
Console.Write(Strings.Main_GetUtc_sdf);
|
||||
socket.Send(ntpData);
|
||||
Console.WriteLine(Strings.OK);
|
||||
Console.Write(Strings.Main_GetUtc_接收请求___);
|
||||
var timeStart = DateTime.Now;
|
||||
socket.Receive(ntpData);
|
||||
ts = DateTime.Now - timeStart;
|
||||
Console.WriteLine(Strings.Main_GetUtc__0_us, ts.TotalMilliseconds);
|
||||
}
|
||||
catch (Exception) {
|
||||
Console.WriteLine(Strings.Timeout);
|
||||
continue;
|
||||
}
|
||||
finally {
|
||||
socket.Close();
|
||||
}
|
||||
|
||||
|
||||
var intPart = ((ulong)ntpData[40] << 24) //
|
||||
| ((ulong)ntpData[41] << 16) //
|
||||
| ((ulong)ntpData[42] << 8) //
|
||||
| ntpData[43];
|
||||
|
||||
var fractPart = ((ulong)ntpData[44] << 24) //
|
||||
| ((ulong)ntpData[45] << 16) //
|
||||
| ((ulong)ntpData[46] << 8) //
|
||||
| ntpData[47];
|
||||
|
||||
var from1900Ms = intPart * 1000 + fractPart * 1000 / 0x100000000L;
|
||||
var onlineTime = new DateTime(1900, 1, 1).AddMilliseconds((long)from1900Ms) + ts;
|
||||
return DateTime.UtcNow - onlineTime;
|
||||
}
|
||||
|
||||
throw new TimeoutException();
|
||||
}
|
||||
|
||||
|
||||
[DllImport("Kernel32.dll")]
|
||||
public static extern unsafe void GetLocalTime(_SYSTEMTIME* st);
|
||||
|
||||
public override void Run()
|
||||
{
|
||||
while (true) {
|
||||
TimeSpan offset;
|
||||
try {
|
||||
offset = GetNtpOffset();
|
||||
}
|
||||
catch (TimeoutException) {
|
||||
Console.Error.WriteLine(Strings.NoService);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
using var tokenSource = new CancellationTokenSource();
|
||||
var token = tokenSource.Token;
|
||||
Task.Run(async () => {
|
||||
for (;;) {
|
||||
if (token.IsCancellationRequested) return;
|
||||
Console.WriteLine(Strings.Main_Run_NTP服务器时间___0_, (DateTime.Now + offset).ToString("O"));
|
||||
Console.WriteLine(Strings.Main_Run_本地时间___0_, DateTime.Now.ToString("O"));
|
||||
Console.WriteLine(offset > TimeSpan.Zero
|
||||
? string.Format(Strings.Main_Run_时差___0__ms, offset.TotalMilliseconds)
|
||||
: string.Format(Strings.Main_Run_时差___1__ms, -offset.TotalMilliseconds));
|
||||
Console.WriteLine(Strings.Main_Run_SyncClock);
|
||||
await Task.Delay(1000, token);
|
||||
Console.Clear();
|
||||
}
|
||||
}, token);
|
||||
|
||||
if (Console.ReadKey().Key == ConsoleKey.Y) {
|
||||
var ntpTime = DateTime.Now - offset;
|
||||
var f = new _SYSTEMTIME {
|
||||
wDay = (ushort)ntpTime.Day
|
||||
, wDayOfWeek = (ushort)ntpTime.DayOfWeek
|
||||
, wHour = (ushort)ntpTime.Hour
|
||||
, wMilliseconds = (ushort)ntpTime.Millisecond
|
||||
, wMinute = (ushort)ntpTime.Minute
|
||||
, wMonth = (ushort)ntpTime.Month
|
||||
, wSecond = (ushort)ntpTime.Second
|
||||
, wYear = (ushort)ntpTime.Year
|
||||
};
|
||||
|
||||
SetLocalTime(f);
|
||||
Console.WriteLine(Strings.Main_Run_SyncDone);
|
||||
tokenSource.Cancel();
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[DllImportAttribute("Kernel32.dll")]
|
||||
public static extern void SetLocalTime(_SYSTEMTIME st);
|
||||
}
|
8
src/Time/Option.cs
Normal file
8
src/Time/Option.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Dot.Time;
|
||||
|
||||
[Verb("time", HelpText = nameof(Strings.HelpForText), ResourceType = typeof(Strings))]
|
||||
public class Option : IOption
|
||||
{
|
||||
[Value(0, HelpText = nameof(Strings.TextTobeProcessed), ResourceType = typeof(Strings))]
|
||||
public string Text { get; set; }
|
||||
}
|
@ -13,6 +13,7 @@ public static class ToolsFactory
|
||||
, Pwd.Option o => new Pwd.Main(o)
|
||||
, Text.Option o => new Text.Main(o)
|
||||
, Guid.Option o => new Guid.Main(o)
|
||||
, Time.Option o => new Time.Main(o)
|
||||
, _ => throw new ArgumentOutOfRangeException(nameof(option))
|
||||
};
|
||||
}
|
||||
|
@ -23,10 +23,10 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommandLineParser" Version="2.9.1"/>
|
||||
<PackageReference Include="NSExt" Version="1.0.6"/>
|
||||
<PackageReference Include="ShellProgressBar" Version="5.2.0"/>
|
||||
<PackageReference Include="TextCopy" Version="6.2.0"/>
|
||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageReference Include="NSExt" Version="1.0.6" />
|
||||
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
|
||||
<PackageReference Include="TextCopy" Version="6.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
Loading…
x
Reference in New Issue
Block a user