wukong-gitlog-cli 0.0.10 → 0.0.11
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/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/src/overtime.mjs +28 -19
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [0.0.11](https://github.com/tomatobybike/wukong-gitlog-cli/compare/v0.0.10...v0.0.11) (2025-11-28)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* 🎸 each hour commit ([029ff72](https://github.com/tomatobybike/wukong-gitlog-cli/commit/029ff72636a47bcb5e77b7fb5acf1ca31d9cf9f3))
|
|
11
|
+
|
|
5
12
|
### [0.0.10](https://github.com/tomatobybike/wukong-gitlog-cli/compare/v0.0.9...v0.0.10) (2025-11-28)
|
|
6
13
|
|
|
7
14
|
|
package/package.json
CHANGED
package/src/overtime.mjs
CHANGED
|
@@ -64,8 +64,10 @@ export function analyzeOvertime(records, opts = {}) {
|
|
|
64
64
|
hd.init('CN');
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
//
|
|
67
|
+
// 新增:每小时分布统计(全部提交)
|
|
68
68
|
const hourlyCommits = Array(24).fill(0);
|
|
69
|
+
// 新增:每小时分布统计(仅加班提交)
|
|
70
|
+
const hourlyOvertimeCommits = Array(24).fill(0);
|
|
69
71
|
records.forEach((r) => {
|
|
70
72
|
const dt = parseCommitDate(r.date);
|
|
71
73
|
if (!dt || !dt.isValid()) return; // skip
|
|
@@ -74,10 +76,13 @@ export function analyzeOvertime(records, opts = {}) {
|
|
|
74
76
|
const isHoliday = !!hd.isHoliday(dt.toDate());
|
|
75
77
|
const isNonWork = isWeekend(dt) || isHoliday;
|
|
76
78
|
|
|
77
|
-
//
|
|
79
|
+
// 每小时分布(全部提交)
|
|
78
80
|
const hour = dt.hour();
|
|
79
81
|
if (hour >= 0 && hour < 24) {
|
|
80
82
|
hourlyCommits[hour]++;
|
|
83
|
+
if (outside) {
|
|
84
|
+
hourlyOvertimeCommits[hour]++;
|
|
85
|
+
}
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
if (outside) {
|
|
@@ -142,8 +147,10 @@ export function analyzeOvertime(records, opts = {}) {
|
|
|
142
147
|
// sort perAuthor by outsideWorkRate desc
|
|
143
148
|
perAuthor.sort((a, b) => b.outsideWorkRate - a.outsideWorkRate || b.total - a.total);
|
|
144
149
|
|
|
145
|
-
//
|
|
150
|
+
// 新增:每小时分布百分比(全部提交)
|
|
146
151
|
const hourlyPercent = hourlyCommits.map(v => total ? +(v / total).toFixed(3) : 0);
|
|
152
|
+
// 新增:每小时分布百分比(仅加班提交)
|
|
153
|
+
const hourlyOvertimePercent = hourlyOvertimeCommits.map(v => total ? +(v / total).toFixed(3) : 0);
|
|
147
154
|
return {
|
|
148
155
|
total,
|
|
149
156
|
outsideWorkCount,
|
|
@@ -165,11 +172,13 @@ export function analyzeOvertime(records, opts = {}) {
|
|
|
165
172
|
holidayRate: total ? +(holidayCount / total).toFixed(3) : 0,
|
|
166
173
|
hourlyCommits,
|
|
167
174
|
hourlyPercent,
|
|
175
|
+
hourlyOvertimeCommits,
|
|
176
|
+
hourlyOvertimePercent,
|
|
168
177
|
};
|
|
169
178
|
}
|
|
170
179
|
|
|
171
180
|
export function renderOvertimeText(stats) {
|
|
172
|
-
const { total, outsideWorkCount, nonWorkdayCount, holidayCount, outsideWorkRate, nonWorkdayRate, holidayRate, perAuthor, startHour, endHour, lunchStart, lunchEnd, country,
|
|
181
|
+
const { total, outsideWorkCount, nonWorkdayCount, holidayCount, outsideWorkRate, nonWorkdayRate, holidayRate, perAuthor, startHour, endHour, lunchStart, lunchEnd, country, hourlyOvertimeCommits = [], hourlyOvertimePercent = [] } = stats;
|
|
173
182
|
const { startCommit, endCommit, latestCommit, latestOutsideCommit } = stats;
|
|
174
183
|
const lines = [];
|
|
175
184
|
|
|
@@ -218,15 +227,15 @@ export function renderOvertimeText(stats) {
|
|
|
218
227
|
lines.push(`下班时间(工作时间外)提交数:${outsideWorkCount},占比:${(outsideWorkRate * 100).toFixed(1)}%`);
|
|
219
228
|
lines.push(`非工作日(周末)提交数:${nonWorkdayCount},占比:${(nonWorkdayRate * 100).toFixed(1)}%`);
|
|
220
229
|
lines.push('');
|
|
221
|
-
lines.push('
|
|
222
|
-
const hourLine = ' Hour |
|
|
230
|
+
lines.push('每小时加班分布(工作时间外提交数/占比):');
|
|
231
|
+
const hourLine = ' Hour | OvertimeCount | Percent';
|
|
223
232
|
lines.push(hourLine);
|
|
224
|
-
lines.push('
|
|
233
|
+
lines.push(' -----|--------------|--------');
|
|
225
234
|
for (let h = 0; h < 24; h++) {
|
|
226
|
-
const cnt =
|
|
235
|
+
const cnt = hourlyOvertimeCommits[h] || 0;
|
|
227
236
|
if (cnt > 0) {
|
|
228
|
-
const pct =
|
|
229
|
-
lines.push(` ${String(h).padStart(2, '0')} | ${String(cnt).padStart(
|
|
237
|
+
const pct = hourlyOvertimePercent[h] ? (hourlyOvertimePercent[h] * 100).toFixed(1) : '0.0';
|
|
238
|
+
lines.push(` ${String(h).padStart(2, '0')} | ${String(cnt).padStart(12, ' ')} | ${pct.padStart(6, ' ')}%`);
|
|
230
239
|
}
|
|
231
240
|
}
|
|
232
241
|
lines.push('');
|
|
@@ -248,7 +257,7 @@ export function renderOvertimeText(stats) {
|
|
|
248
257
|
}
|
|
249
258
|
|
|
250
259
|
export function renderOvertimeTab(stats) {
|
|
251
|
-
const { total, outsideWorkCount, nonWorkdayCount, holidayCount, outsideWorkRate, nonWorkdayRate, holidayRate, perAuthor, startHour, endHour, lunchStart, lunchEnd, country,
|
|
260
|
+
const { total, outsideWorkCount, nonWorkdayCount, holidayCount, outsideWorkRate, nonWorkdayRate, holidayRate, perAuthor, startHour, endHour, lunchStart, lunchEnd, country, hourlyOvertimeCommits = [], hourlyOvertimePercent = [] } = stats;
|
|
252
261
|
const { startCommit, endCommit, latestCommit, latestOutsideCommit } = stats;
|
|
253
262
|
const rows = [];
|
|
254
263
|
rows.push(`总提交数:\t${total}`);
|
|
@@ -260,12 +269,12 @@ export function renderOvertimeTab(stats) {
|
|
|
260
269
|
rows.push(`下班时间(工作时间外)提交数:\t${outsideWorkCount}\t占比:\t${(outsideWorkRate * 100).toFixed(1)}%`);
|
|
261
270
|
rows.push(`非工作日(周末)提交数:\t${nonWorkdayCount}\t占比:\t${(nonWorkdayRate * 100).toFixed(1)}%`);
|
|
262
271
|
rows.push('');
|
|
263
|
-
rows.push('
|
|
264
|
-
rows.push(['Hour', '
|
|
272
|
+
rows.push('每小时加班分布(工作时间外提交数/占比):');
|
|
273
|
+
rows.push(['Hour', 'OvertimeCount', 'Percent'].join('\t'));
|
|
265
274
|
for (let h = 0; h < 24; h++) {
|
|
266
|
-
const cnt =
|
|
275
|
+
const cnt = hourlyOvertimeCommits[h] || 0;
|
|
267
276
|
if (cnt > 0) {
|
|
268
|
-
const pct =
|
|
277
|
+
const pct = hourlyOvertimePercent[h] ? (hourlyOvertimePercent[h] * 100).toFixed(1) : '0.0';
|
|
269
278
|
rows.push([String(h).padStart(2, '0'), cnt, `${pct}%`].join('\t'));
|
|
270
279
|
}
|
|
271
280
|
}
|
|
@@ -286,18 +295,18 @@ function escapeCsv(v) {
|
|
|
286
295
|
}
|
|
287
296
|
|
|
288
297
|
export function renderOvertimeCsv(stats) {
|
|
289
|
-
const { perAuthor, latestOutsideCommit, country,
|
|
298
|
+
const { perAuthor, latestOutsideCommit, country, hourlyOvertimeCommits = [], hourlyOvertimePercent = [], total = 0 } = stats;
|
|
290
299
|
const rows = [];
|
|
291
300
|
if (latestOutsideCommit) {
|
|
292
301
|
rows.push(`# 加班最晚的一次提交,Hash,Author,Date,Message`);
|
|
293
302
|
rows.push(`# ,${escapeCsv(latestOutsideCommit.hash)},${escapeCsv(latestOutsideCommit.author)},${escapeCsv(formatDateForCountry(latestOutsideCommit.date, country))},${escapeCsv(latestOutsideCommit.message)}`);
|
|
294
303
|
}
|
|
295
304
|
rows.push('');
|
|
296
|
-
rows.push('Hour,
|
|
305
|
+
rows.push('Hour,OvertimeCount,Percent');
|
|
297
306
|
for (let h = 0; h < 24; h++) {
|
|
298
|
-
const cnt =
|
|
307
|
+
const cnt = hourlyOvertimeCommits[h] || 0;
|
|
299
308
|
if (cnt > 0) {
|
|
300
|
-
const pct =
|
|
309
|
+
const pct = hourlyOvertimePercent[h] ? (hourlyOvertimePercent[h] * 100).toFixed(1) : '0.0';
|
|
301
310
|
rows.push(`${h.toString().padStart(2, '0')},${cnt},${pct}%`);
|
|
302
311
|
}
|
|
303
312
|
}
|