Initial commit to new repository
This commit is contained in:
128
src/AxCopilot/Handlers/DateCalcHandler.cs
Normal file
128
src/AxCopilot/Handlers/DateCalcHandler.cs
Normal file
@@ -0,0 +1,128 @@
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows;
|
||||
using AxCopilot.SDK;
|
||||
using AxCopilot.Themes;
|
||||
|
||||
namespace AxCopilot.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 날짜/시간 변환기 핸들러. "date" 프리픽스로 사용합니다.
|
||||
/// 예: date → 현재 날짜/시간 + 유닉스 타임스탬프
|
||||
/// date +30d → 오늘 + 30일
|
||||
/// date -100d → 오늘 - 100일
|
||||
/// date 2026-12-25 → 해당 날짜까지 D-day + 요일
|
||||
/// date 1711584000 → 유닉스 타임스탬프 → 날짜
|
||||
/// date to unix → 현재 시각의 유닉스 타임스탬프
|
||||
/// Enter → 결과를 클립보드에 복사.
|
||||
/// </summary>
|
||||
public class DateCalcHandler : IActionHandler
|
||||
{
|
||||
public string? Prefix => "date";
|
||||
|
||||
public PluginMetadata Metadata => new(
|
||||
"DateCalc",
|
||||
"날짜 계산 · D-day · 타임스탬프 변환",
|
||||
"1.0",
|
||||
"AX");
|
||||
|
||||
private static readonly string[] DateFormats =
|
||||
["yyyy-MM-dd", "yyyy/MM/dd", "yyyyMMdd", "MM/dd/yyyy", "dd-MM-yyyy"];
|
||||
|
||||
public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
|
||||
{
|
||||
var q = query.Trim();
|
||||
var now = DateTime.Now;
|
||||
var items = new List<LauncherItem>();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(q))
|
||||
{
|
||||
// 현재 날짜/시간 정보
|
||||
var dayName = now.ToString("dddd", new CultureInfo("ko-KR"));
|
||||
items.Add(Item($"{now:yyyy-MM-dd} ({dayName})", $"{now:HH:mm:ss} · {now:yyyy-MM-dd}"));
|
||||
items.Add(Item($"유닉스 타임스탬프: {new DateTimeOffset(now).ToUnixTimeSeconds()}", "현재 시각의 Unix epoch"));
|
||||
items.Add(Item($"올해 {now.DayOfYear}일째 / 남은 일: {(new DateTime(now.Year, 12, 31) - now).Days}일",
|
||||
$"ISO 주차: {ISOWeek.GetWeekOfYear(now)}주"));
|
||||
return Task.FromResult<IEnumerable<LauncherItem>>(items);
|
||||
}
|
||||
|
||||
// +30d / -100d 패턴
|
||||
var offsetMatch = Regex.Match(q, @"^([+-])(\d+)([dDwWmMyY])$");
|
||||
if (offsetMatch.Success)
|
||||
{
|
||||
var sign = offsetMatch.Groups[1].Value == "+" ? 1 : -1;
|
||||
var val = int.Parse(offsetMatch.Groups[2].Value) * sign;
|
||||
var unit = offsetMatch.Groups[3].Value.ToLowerInvariant();
|
||||
var target = unit switch
|
||||
{
|
||||
"d" => now.AddDays(val),
|
||||
"w" => now.AddDays(val * 7),
|
||||
"m" => now.AddMonths(val),
|
||||
"y" => now.AddYears(val),
|
||||
_ => now
|
||||
};
|
||||
var dayName = target.ToString("dddd", new CultureInfo("ko-KR"));
|
||||
var diff = (target.Date - now.Date).Days;
|
||||
var diffStr = diff >= 0 ? $"오늘로부터 {diff}일 후" : $"오늘로부터 {Math.Abs(diff)}일 전";
|
||||
|
||||
items.Add(Item($"{target:yyyy-MM-dd} ({dayName})", diffStr));
|
||||
return Task.FromResult<IEnumerable<LauncherItem>>(items);
|
||||
}
|
||||
|
||||
// 유닉스 타임스탬프 (10자리 또는 13자리 숫자)
|
||||
if (Regex.IsMatch(q, @"^\d{10,13}$") && long.TryParse(q, out long epoch))
|
||||
{
|
||||
var ts = epoch > 9_999_999_999 ? epoch / 1000 : epoch; // 밀리초→초
|
||||
var dt = DateTimeOffset.FromUnixTimeSeconds(ts).LocalDateTime;
|
||||
var dayName = dt.ToString("dddd", new CultureInfo("ko-KR"));
|
||||
items.Add(Item($"{dt:yyyy-MM-dd HH:mm:ss} ({dayName})", $"Unix {epoch} → 로컬 시간"));
|
||||
return Task.FromResult<IEnumerable<LauncherItem>>(items);
|
||||
}
|
||||
|
||||
// "to unix" / "unix" 키워드
|
||||
if (q.Equals("unix", StringComparison.OrdinalIgnoreCase) ||
|
||||
q.Equals("to unix", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var unix = new DateTimeOffset(now).ToUnixTimeSeconds();
|
||||
items.Add(Item($"{unix}", $"현재 시각 ({now:yyyy-MM-dd HH:mm:ss}) → Unix 타임스탬프"));
|
||||
return Task.FromResult<IEnumerable<LauncherItem>>(items);
|
||||
}
|
||||
|
||||
// 날짜 파싱 → D-day 계산
|
||||
if (DateTime.TryParseExact(q, DateFormats, CultureInfo.InvariantCulture,
|
||||
DateTimeStyles.None, out var parsed))
|
||||
{
|
||||
var dayName = parsed.ToString("dddd", new CultureInfo("ko-KR"));
|
||||
var diff = (parsed.Date - now.Date).Days;
|
||||
var dday = diff switch
|
||||
{
|
||||
0 => "오늘",
|
||||
> 0 => $"D-{diff} (앞으로 {diff}일)",
|
||||
_ => $"D+{Math.Abs(diff)} ({Math.Abs(diff)}일 지남)"
|
||||
};
|
||||
|
||||
items.Add(Item($"{parsed:yyyy-MM-dd} ({dayName})", dday));
|
||||
return Task.FromResult<IEnumerable<LauncherItem>>(items);
|
||||
}
|
||||
|
||||
items.Add(new LauncherItem(
|
||||
"날짜 형식을 인식할 수 없습니다",
|
||||
"예: +30d, -100d, 2026-12-25, 1711584000, unix",
|
||||
null, null, Symbol: Symbols.Warning));
|
||||
|
||||
return Task.FromResult<IEnumerable<LauncherItem>>(items);
|
||||
}
|
||||
|
||||
private static LauncherItem Item(string title, string subtitle) =>
|
||||
new(title, $"{subtitle} · Enter로 복사", null, title, Symbol: Symbols.Clock);
|
||||
|
||||
public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
|
||||
{
|
||||
if (item.Data is string text && !string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
try { Application.Current?.Dispatcher.Invoke(() => Clipboard.SetText(text)); }
|
||||
catch { }
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user