@godcreator/gwb-time 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +29 -2
- package/dist/client.js +73 -0
- package/dist/index.js +94 -0
- package/dist/style.css +143 -0
- package/package.json +34 -3
- package/skills/time/SKILL.md +39 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 godcreator02
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
-
#
|
|
1
|
+
# gwb-time
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
东八区(UTC+8)时间。用户常在亚洲与美国之间往返,电脑的时区跟着变;写进文件名、目录名、id 的时间一律用东八区,
|
|
4
|
+
同一时刻起的名字不管人在哪儿都一样。
|
|
5
|
+
|
|
6
|
+
| 包 | 在哪 | 做什么 |
|
|
7
|
+
| --- | --- | --- |
|
|
8
|
+
| `@godcreator/utc8-time` | `packages/utc8-time/` | 库,零依赖:`utc8PartsOf`、`formatUtc8(at, 'yyMMddHHmm')`、`utc8Iso`,node 与浏览器都能用 |
|
|
9
|
+
| `@godcreator/gwb-time` | `plugins/time/` | gwb 插件:状态栏右侧显示东八区的月日时分;命令 `time.now` 回起文件名常用的几种写法;随包说明书 `time` |
|
|
10
|
+
|
|
11
|
+
插件把库打包进自己的产物,装插件不需要另装库;别的仓的代码要东八区时间就直接依赖库。
|
|
12
|
+
|
|
13
|
+
## 插件
|
|
14
|
+
|
|
15
|
+
- **状态栏时钟**:登记成外壳的只显示格子(`registerStatusItem` 带 `kind: 'label'`,外壳 0.15.13 起),浏览器侧导出
|
|
16
|
+
`mountStatusLabel`,显示 `MM-dd HH:mm`,每到整分钟换字。没有窗格
|
|
17
|
+
- **`time.now`**:无参数,`effect: read`。回执 `data` 的键就是排法:`yyMMddHHmm`、`yyyyMMddHHmmss`、`yyyy-MM-dd`、
|
|
18
|
+
`yyyy-MM-ddTHH:mm`,另有带 `+08:00` 的 `iso`
|
|
19
|
+
- **说明书 `time`**:agent 起时间文件名先调 `time.now`,代码里用库,不用 `getHours()` 与 `toISOString()`
|
|
20
|
+
|
|
21
|
+
## 构建与检查(仓根)
|
|
22
|
+
|
|
23
|
+
```powershell
|
|
24
|
+
pnpm install
|
|
25
|
+
pnpm build # 先构建库,再构建插件(esbuild 打包 node 侧与浏览器侧、tailwindcss 生成样式)
|
|
26
|
+
pnpm check # 各包的 typecheck、lint、vitest
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
在隔离 home 里验证与发版照说明书 `gwb-devkit`,版本号照 `gwb-release`。发版时 `packages` 写
|
|
30
|
+
`["packages/utc8-time", "plugins/time"]`,库在前。
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// src/client/index.tsx
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { createRoot } from "react-dom/client";
|
|
4
|
+
|
|
5
|
+
// ../../packages/utc8-time/dist/index.js
|
|
6
|
+
var UTC8_OFFSET_MS = 8 * 60 * 60 * 1e3;
|
|
7
|
+
function utc8PartsOf(at) {
|
|
8
|
+
const ms = at.getTime();
|
|
9
|
+
if (Number.isNaN(ms))
|
|
10
|
+
throw new Error("utc8PartsOf \u6536\u5230\u7684\u662F\u65E0\u6548\u7684 Date\uFF08getTime() \u662F NaN\uFF09");
|
|
11
|
+
const shifted = new Date(ms + UTC8_OFFSET_MS);
|
|
12
|
+
return {
|
|
13
|
+
year: shifted.getUTCFullYear(),
|
|
14
|
+
month: shifted.getUTCMonth() + 1,
|
|
15
|
+
day: shifted.getUTCDate(),
|
|
16
|
+
hour: shifted.getUTCHours(),
|
|
17
|
+
minute: shifted.getUTCMinutes(),
|
|
18
|
+
second: shifted.getUTCSeconds(),
|
|
19
|
+
weekday: (shifted.getUTCDay() + 6) % 7
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
var pad = (value, width) => String(value).padStart(width, "0");
|
|
23
|
+
var TOKEN = /yyyy|yy|MM|dd|HH|mm|ss/g;
|
|
24
|
+
function formatUtc8(at, pattern) {
|
|
25
|
+
const parts = utc8PartsOf(at);
|
|
26
|
+
return pattern.replace(TOKEN, (token) => {
|
|
27
|
+
switch (token) {
|
|
28
|
+
case "yyyy":
|
|
29
|
+
return pad(parts.year, 4);
|
|
30
|
+
case "yy":
|
|
31
|
+
return pad(parts.year % 100, 2);
|
|
32
|
+
case "MM":
|
|
33
|
+
return pad(parts.month, 2);
|
|
34
|
+
case "dd":
|
|
35
|
+
return pad(parts.day, 2);
|
|
36
|
+
case "HH":
|
|
37
|
+
return pad(parts.hour, 2);
|
|
38
|
+
case "mm":
|
|
39
|
+
return pad(parts.minute, 2);
|
|
40
|
+
default:
|
|
41
|
+
return pad(parts.second, 2);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/client/next-minute.ts
|
|
47
|
+
function msUntilNextMinute(at) {
|
|
48
|
+
return 6e4 - at.getTime() % 6e4;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/client/index.tsx
|
|
52
|
+
import { jsx } from "react/jsx-runtime";
|
|
53
|
+
function Utc8Clock() {
|
|
54
|
+
const [now, setNow] = useState(() => /* @__PURE__ */ new Date());
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
const timer = setTimeout(() => setNow(/* @__PURE__ */ new Date()), msUntilNextMinute(now));
|
|
57
|
+
return () => clearTimeout(timer);
|
|
58
|
+
}, [now]);
|
|
59
|
+
return /* @__PURE__ */ jsx("span", { className: "time:font-mono time:tabular-nums", children: formatUtc8(now, "MM-dd HH:mm") });
|
|
60
|
+
}
|
|
61
|
+
function mountStatusLabel(_args, container) {
|
|
62
|
+
const root = createRoot(container);
|
|
63
|
+
root.render(/* @__PURE__ */ jsx(Utc8Clock, {}));
|
|
64
|
+
return {
|
|
65
|
+
dispose() {
|
|
66
|
+
root.unmount();
|
|
67
|
+
container.textContent = "";
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export {
|
|
72
|
+
mountStatusLabel
|
|
73
|
+
};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { createRequire as __createRequire } from "node:module";
|
|
2
|
+
const require = __createRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// ../../packages/utc8-time/dist/index.js
|
|
5
|
+
var UTC8_OFFSET_MS = 8 * 60 * 60 * 1e3;
|
|
6
|
+
function utc8PartsOf(at) {
|
|
7
|
+
const ms = at.getTime();
|
|
8
|
+
if (Number.isNaN(ms))
|
|
9
|
+
throw new Error("utc8PartsOf \u6536\u5230\u7684\u662F\u65E0\u6548\u7684 Date\uFF08getTime() \u662F NaN\uFF09");
|
|
10
|
+
const shifted = new Date(ms + UTC8_OFFSET_MS);
|
|
11
|
+
return {
|
|
12
|
+
year: shifted.getUTCFullYear(),
|
|
13
|
+
month: shifted.getUTCMonth() + 1,
|
|
14
|
+
day: shifted.getUTCDate(),
|
|
15
|
+
hour: shifted.getUTCHours(),
|
|
16
|
+
minute: shifted.getUTCMinutes(),
|
|
17
|
+
second: shifted.getUTCSeconds(),
|
|
18
|
+
weekday: (shifted.getUTCDay() + 6) % 7
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
var pad = (value, width) => String(value).padStart(width, "0");
|
|
22
|
+
var TOKEN = /yyyy|yy|MM|dd|HH|mm|ss/g;
|
|
23
|
+
function formatUtc8(at, pattern) {
|
|
24
|
+
const parts = utc8PartsOf(at);
|
|
25
|
+
return pattern.replace(TOKEN, (token) => {
|
|
26
|
+
switch (token) {
|
|
27
|
+
case "yyyy":
|
|
28
|
+
return pad(parts.year, 4);
|
|
29
|
+
case "yy":
|
|
30
|
+
return pad(parts.year % 100, 2);
|
|
31
|
+
case "MM":
|
|
32
|
+
return pad(parts.month, 2);
|
|
33
|
+
case "dd":
|
|
34
|
+
return pad(parts.day, 2);
|
|
35
|
+
case "HH":
|
|
36
|
+
return pad(parts.hour, 2);
|
|
37
|
+
case "mm":
|
|
38
|
+
return pad(parts.minute, 2);
|
|
39
|
+
default:
|
|
40
|
+
return pad(parts.second, 2);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function utc8Iso(at) {
|
|
45
|
+
return `${formatUtc8(at, "yyyy-MM-ddTHH:mm:ss")}+08:00`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// src/now.ts
|
|
49
|
+
function utc8NowReply(at) {
|
|
50
|
+
return {
|
|
51
|
+
yyMMddHHmm: formatUtc8(at, "yyMMddHHmm"),
|
|
52
|
+
yyyyMMddHHmmss: formatUtc8(at, "yyyyMMddHHmmss"),
|
|
53
|
+
"yyyy-MM-dd": formatUtc8(at, "yyyy-MM-dd"),
|
|
54
|
+
"yyyy-MM-ddTHH:mm": formatUtc8(at, "yyyy-MM-ddTHH:mm"),
|
|
55
|
+
iso: utc8Iso(at)
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/index.ts
|
|
60
|
+
var name = "gwb-time";
|
|
61
|
+
var CLIENT_URL = new URL("./client.js", import.meta.url).href;
|
|
62
|
+
var STYLE_URL = new URL("./style.css", import.meta.url).href;
|
|
63
|
+
var SKILLS_DIR = new URL("../skills/", import.meta.url);
|
|
64
|
+
var inject = ["gwbCommands", "gwbShell"];
|
|
65
|
+
function apply(ctx) {
|
|
66
|
+
const commands = ctx.gwbCommands;
|
|
67
|
+
if (commands === void 0) throw new Error("ctx.gwbCommands \u4E0D\u5728\uFF1Ainject \u91CC\u5199\u4E86\u5B83\uFF0Ccordis \u672C\u4E0D\u8BE5\u8C03\u7528 apply");
|
|
68
|
+
ctx.gwbShell.describeSelf({ title: "\u4E1C\u516B\u533A\u65F6\u95F4", icon: "clock" });
|
|
69
|
+
ctx.gwbShell.registerStatusItem({
|
|
70
|
+
id: "clock",
|
|
71
|
+
title: "\u4E1C\u516B\u533A\u65F6\u95F4\uFF08UTC+8\uFF09\uFF0C\u4E0D\u8DDF\u672C\u673A\u65F6\u533A\u8D70",
|
|
72
|
+
icon: "clock",
|
|
73
|
+
kind: "label",
|
|
74
|
+
client: CLIENT_URL,
|
|
75
|
+
style: STYLE_URL
|
|
76
|
+
});
|
|
77
|
+
commands.register(
|
|
78
|
+
{
|
|
79
|
+
name: "time.now",
|
|
80
|
+
description: "\u4E1C\u516B\u533A\uFF08UTC+8\uFF09\u73B0\u5728\u7684\u65F6\u95F4\uFF0C\u6392\u6210\u8D77\u6587\u4EF6\u540D\u3001\u76EE\u5F55\u540D\u3001id \u5E38\u7528\u7684\u51E0\u79CD\u5199\u6CD5\uFF1B\u4E0D\u8DDF\u672C\u673A\u65F6\u533A\u8D70",
|
|
81
|
+
usage: "\u65E0\u53C2\u6570\u3002data \u7684\u952E\u5C31\u662F\u6392\u6CD5\uFF1AyyMMddHHmm\uFF08\u5982 2610181128\uFF0Cprobes \u76EE\u5F55\u540D\u7528\u5B83\uFF09\u3001yyyyMMddHHmmss\u3001yyyy-MM-dd\u3001yyyy-MM-ddTHH:mm\uFF08\u8F68\u8FF9\u5361 born-at \u7528\u5B83\uFF09\uFF0Ciso \u662F\u5E26 +08:00 \u7684 ISO 8601\uFF08\u5230\u79D2\uFF09",
|
|
82
|
+
effect: "read"
|
|
83
|
+
},
|
|
84
|
+
async () => ({ ok: true, data: utc8NowReply(/* @__PURE__ */ new Date()) })
|
|
85
|
+
);
|
|
86
|
+
ctx.inject(["gwbSkills"], (c) => {
|
|
87
|
+
c.effect(() => c.gwbSkills.register(SKILLS_DIR));
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
export {
|
|
91
|
+
apply,
|
|
92
|
+
inject,
|
|
93
|
+
name
|
|
94
|
+
};
|
package/dist/style.css
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties;
|
|
3
|
+
@layer utilities {
|
|
4
|
+
.time\:font-mono {
|
|
5
|
+
font-family: var(--gwb-font-mono);
|
|
6
|
+
}
|
|
7
|
+
.time\:tabular-nums {
|
|
8
|
+
--tw-numeric-spacing: tabular-nums;
|
|
9
|
+
font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
@property --tw-animation-delay {
|
|
13
|
+
syntax: "*";
|
|
14
|
+
inherits: false;
|
|
15
|
+
initial-value: 0s;
|
|
16
|
+
}
|
|
17
|
+
@property --tw-animation-direction {
|
|
18
|
+
syntax: "*";
|
|
19
|
+
inherits: false;
|
|
20
|
+
initial-value: normal;
|
|
21
|
+
}
|
|
22
|
+
@property --tw-animation-duration {
|
|
23
|
+
syntax: "*";
|
|
24
|
+
inherits: false;
|
|
25
|
+
}
|
|
26
|
+
@property --tw-animation-fill-mode {
|
|
27
|
+
syntax: "*";
|
|
28
|
+
inherits: false;
|
|
29
|
+
initial-value: none;
|
|
30
|
+
}
|
|
31
|
+
@property --tw-animation-iteration-count {
|
|
32
|
+
syntax: "*";
|
|
33
|
+
inherits: false;
|
|
34
|
+
initial-value: 1;
|
|
35
|
+
}
|
|
36
|
+
@property --tw-enter-blur {
|
|
37
|
+
syntax: "*";
|
|
38
|
+
inherits: false;
|
|
39
|
+
initial-value: 0;
|
|
40
|
+
}
|
|
41
|
+
@property --tw-enter-opacity {
|
|
42
|
+
syntax: "*";
|
|
43
|
+
inherits: false;
|
|
44
|
+
initial-value: 1;
|
|
45
|
+
}
|
|
46
|
+
@property --tw-enter-rotate {
|
|
47
|
+
syntax: "*";
|
|
48
|
+
inherits: false;
|
|
49
|
+
initial-value: 0;
|
|
50
|
+
}
|
|
51
|
+
@property --tw-enter-scale {
|
|
52
|
+
syntax: "*";
|
|
53
|
+
inherits: false;
|
|
54
|
+
initial-value: 1;
|
|
55
|
+
}
|
|
56
|
+
@property --tw-enter-translate-x {
|
|
57
|
+
syntax: "*";
|
|
58
|
+
inherits: false;
|
|
59
|
+
initial-value: 0;
|
|
60
|
+
}
|
|
61
|
+
@property --tw-enter-translate-y {
|
|
62
|
+
syntax: "*";
|
|
63
|
+
inherits: false;
|
|
64
|
+
initial-value: 0;
|
|
65
|
+
}
|
|
66
|
+
@property --tw-exit-blur {
|
|
67
|
+
syntax: "*";
|
|
68
|
+
inherits: false;
|
|
69
|
+
initial-value: 0;
|
|
70
|
+
}
|
|
71
|
+
@property --tw-exit-opacity {
|
|
72
|
+
syntax: "*";
|
|
73
|
+
inherits: false;
|
|
74
|
+
initial-value: 1;
|
|
75
|
+
}
|
|
76
|
+
@property --tw-exit-rotate {
|
|
77
|
+
syntax: "*";
|
|
78
|
+
inherits: false;
|
|
79
|
+
initial-value: 0;
|
|
80
|
+
}
|
|
81
|
+
@property --tw-exit-scale {
|
|
82
|
+
syntax: "*";
|
|
83
|
+
inherits: false;
|
|
84
|
+
initial-value: 1;
|
|
85
|
+
}
|
|
86
|
+
@property --tw-exit-translate-x {
|
|
87
|
+
syntax: "*";
|
|
88
|
+
inherits: false;
|
|
89
|
+
initial-value: 0;
|
|
90
|
+
}
|
|
91
|
+
@property --tw-exit-translate-y {
|
|
92
|
+
syntax: "*";
|
|
93
|
+
inherits: false;
|
|
94
|
+
initial-value: 0;
|
|
95
|
+
}
|
|
96
|
+
@property --tw-ordinal {
|
|
97
|
+
syntax: "*";
|
|
98
|
+
inherits: false;
|
|
99
|
+
}
|
|
100
|
+
@property --tw-slashed-zero {
|
|
101
|
+
syntax: "*";
|
|
102
|
+
inherits: false;
|
|
103
|
+
}
|
|
104
|
+
@property --tw-numeric-figure {
|
|
105
|
+
syntax: "*";
|
|
106
|
+
inherits: false;
|
|
107
|
+
}
|
|
108
|
+
@property --tw-numeric-spacing {
|
|
109
|
+
syntax: "*";
|
|
110
|
+
inherits: false;
|
|
111
|
+
}
|
|
112
|
+
@property --tw-numeric-fraction {
|
|
113
|
+
syntax: "*";
|
|
114
|
+
inherits: false;
|
|
115
|
+
}
|
|
116
|
+
@layer properties {
|
|
117
|
+
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
|
|
118
|
+
*, ::before, ::after, ::backdrop {
|
|
119
|
+
--tw-ordinal: initial;
|
|
120
|
+
--tw-slashed-zero: initial;
|
|
121
|
+
--tw-numeric-figure: initial;
|
|
122
|
+
--tw-numeric-spacing: initial;
|
|
123
|
+
--tw-numeric-fraction: initial;
|
|
124
|
+
--tw-animation-delay: 0s;
|
|
125
|
+
--tw-animation-direction: normal;
|
|
126
|
+
--tw-animation-duration: initial;
|
|
127
|
+
--tw-animation-fill-mode: none;
|
|
128
|
+
--tw-animation-iteration-count: 1;
|
|
129
|
+
--tw-enter-blur: 0;
|
|
130
|
+
--tw-enter-opacity: 1;
|
|
131
|
+
--tw-enter-rotate: 0;
|
|
132
|
+
--tw-enter-scale: 1;
|
|
133
|
+
--tw-enter-translate-x: 0;
|
|
134
|
+
--tw-enter-translate-y: 0;
|
|
135
|
+
--tw-exit-blur: 0;
|
|
136
|
+
--tw-exit-opacity: 1;
|
|
137
|
+
--tw-exit-rotate: 0;
|
|
138
|
+
--tw-exit-scale: 1;
|
|
139
|
+
--tw-exit-translate-x: 0;
|
|
140
|
+
--tw-exit-translate-y: 0;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@godcreator/gwb-time",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "东八区时间:状态栏右侧显示东八区(UTC+8)的月日时分,命令 time.now 回起文件名常用的几种东八区时间写法,都不跟本机时区走;随包说明书 time 讲 agent 起时间文件名的规矩",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"skills",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"keywords": [
|
|
16
|
+
"gwb-plugin"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"registry": "https://registry.npmjs.org/",
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"@godcreator/gwb-commands": "^0.6.2",
|
|
24
|
+
"@godcreator/gwb-kernel-desktop": "^0.10.2",
|
|
25
|
+
"@godcreator/gwb-shell": "^0.15.13",
|
|
26
|
+
"@godcreator/gwb-skills": "^0.4.14"
|
|
27
|
+
},
|
|
28
|
+
"peerDependenciesMeta": {
|
|
29
|
+
"@godcreator/gwb-skills": {
|
|
30
|
+
"optional": true
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/godcreator02/gwb-time.git"
|
|
36
|
+
}
|
|
6
37
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: time
|
|
3
|
+
description: 要用时间起文件名、目录名、id(probes 目录、轨迹卡日期与 born-at、反馈文件、记录 id 这类),或要知道东八区现在几点时读。这些时间一律用东八区(UTC+8),不用本机时区:用户常在亚洲与美国之间往返,本机时区会跟着变。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 东八区时间
|
|
7
|
+
|
|
8
|
+
用户常在亚洲与美国之间往返,电脑的时区跟着切换。**写进文件名、目录名、id、frontmatter 的时间一律用东八区(UTC+8)**,
|
|
9
|
+
这样同一时刻起的名字不管人在哪儿都一样,按名字排序也就是按时间排序。
|
|
10
|
+
|
|
11
|
+
## agent 起名字
|
|
12
|
+
|
|
13
|
+
先调 `time.now`(无参数),从回执里取对应的那一种写法,不在 shell 里用 `Get-Date`、`date` 取本机时间:
|
|
14
|
+
|
|
15
|
+
| 回执的键 | 例子 | 用在哪 |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| `yyMMddHHmm` | `2610181128` | probes 目录名、反馈文件名里的时间戳 |
|
|
18
|
+
| `yyyyMMddHHmmss` | `20261018112805` | 要到秒的 id |
|
|
19
|
+
| `yyyy-MM-dd` | `2026-10-18` | 轨迹卡文件名的日期、按天分的文件 |
|
|
20
|
+
| `yyyy-MM-ddTHH:mm` | `2026-10-18T11:28` | 轨迹卡的 `born-at` |
|
|
21
|
+
| `iso` | `2026-10-18T11:28:05+08:00` | 要写明时区的地方 |
|
|
22
|
+
|
|
23
|
+
工作台没启动、调不了命令时,用 pwsh 现算:`[DateTimeOffset]::UtcNow.ToOffset([TimeSpan]::FromHours(8)).ToString('yyMMddHHmm')`。
|
|
24
|
+
|
|
25
|
+
## 代码里取东八区时间
|
|
26
|
+
|
|
27
|
+
用包 `@godcreator/utc8-time`(零依赖,node 与浏览器都能用),不用 `getHours()` 这类读本机时区的方法,也不用 `toISOString()`(那是 UTC):
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { formatUtc8, utc8Iso, utc8PartsOf } from '@godcreator/utc8-time'
|
|
31
|
+
|
|
32
|
+
formatUtc8(new Date(), 'yyMMddHHmm') // 占位符 yyyy yy MM dd HH mm ss,其余字符原样保留
|
|
33
|
+
utc8Iso(new Date()) // 2026-10-18T11:28:05+08:00
|
|
34
|
+
utc8PartsOf(new Date()) // { year, month, day, hour, minute, second, weekday },weekday 0 = 周一
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 状态栏
|
|
38
|
+
|
|
39
|
+
插件在状态栏右侧显示东八区的月日时分(`10-18 11:28`),悬停提示写明是东八区。
|