Skip to content

Commit cd973b2

Browse files
fix(frontend): 2月29日を誕生日に設定している場合、平年は3月1日を誕生日として扱うように (#17072)
* fix(frontend): 2月29日を誕生日に設定している場合、平年は3月1日を誕生日として扱うように * Update Changelog * add tests * spdx
1 parent 666f78e commit cd973b2

File tree

5 files changed

+92
-16
lines changed

5 files changed

+92
-16
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
- Fix: ドライブのソートが「登録日(昇順)」の場合に正しく動作しない問題を修正
2020
- Fix: 管理画面でアーカイブ済のお知らせを表示した際にアクティブなお知らせが多い旨の警告が出る問題を修正
2121
- Fix: ファイルタブのセンシティブメディアを開く際に確認ダイアログを出す設定が適用されない問題を修正
22+
- Fix: 2月29日を誕生日に設定している場合、閏年以外は3月1日を誕生日として扱うように修正
2223

2324
### Server
2425
- Enhance: OAuthのクライアント情報取得(Client Information Discovery)において、IndieWeb Living Standard 11 July 2024で定義されているJSONドキュメント形式に対応しました

packages/frontend/src/boot/main-boot.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { prefer } from '@/preferences.js';
2929
import { updateCurrentAccountPartial } from '@/accounts.js';
3030
import { migrateOldSettings } from '@/pref-migrate.js';
3131
import { unisonReload } from '@/utility/unison-reload.js';
32+
import { isBirthday } from '@/utility/is-birthday.js';
3233

3334
export async function mainBoot() {
3435
const { isClientUpdated, lastVersion } = await common(async () => {
@@ -144,12 +145,8 @@ export async function mainBoot() {
144145
const m = now.getMonth() + 1;
145146
const d = now.getDate();
146147

147-
if ($i.birthday) {
148-
const bm = parseInt($i.birthday.split('-')[1]);
149-
const bd = parseInt($i.birthday.split('-')[2]);
150-
if (m === bm && d === bd) {
151-
claimAchievement('loggedInOnBirthday');
152-
}
148+
if (isBirthday($i, now)) {
149+
claimAchievement('loggedInOnBirthday');
153150
}
154151

155152
if (m === 1 && d === 1) {

packages/frontend/src/pages/user/home.vue

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ import { getStaticImageUrl } from '@/utility/media-proxy.js';
186186
import MkSparkle from '@/components/MkSparkle.vue';
187187
import { prefer } from '@/preferences.js';
188188
import MkPullToRefresh from '@/components/MkPullToRefresh.vue';
189+
import { isBirthday } from '@/utility/is-birthday.js';
189190
190191
function calcAge(birthdate: string): number {
191192
const date = new Date(birthdate);
@@ -319,16 +320,10 @@ function disposeBannerParallaxResizeObserver() {
319320
onMounted(() => {
320321
narrow.value = rootEl.value!.clientWidth < 1000;
321322
322-
if (props.user.birthday) {
323-
const m = new Date().getMonth() + 1;
324-
const d = new Date().getDate();
325-
const bm = parseInt(props.user.birthday.split('-')[1]);
326-
const bd = parseInt(props.user.birthday.split('-')[2]);
327-
if (m === bm && d === bd) {
328-
confetti({
329-
duration: 1000 * 4,
330-
});
331-
}
323+
if (isBirthday(user.value)) {
324+
confetti({
325+
duration: 1000 * 4,
326+
});
332327
}
333328
334329
nextTick(() => {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* SPDX-FileCopyrightText: syuilo and misskey-project
3+
* SPDX-License-Identifier: AGPL-3.0-only
4+
*/
5+
6+
import * as Misskey from 'misskey-js';
7+
8+
export function isBirthday(user: Misskey.entities.UserDetailed, now = new Date()): boolean {
9+
if (user.birthday == null) return false;
10+
11+
const [_, bm, bd] = user.birthday.split('-').map((v) => parseInt(v, 10));
12+
if (isNaN(bm) || isNaN(bd)) return false;
13+
14+
const y = now.getFullYear();
15+
const m = now.getMonth() + 1;
16+
const d = now.getDate();
17+
18+
// 閏日生まれで平年の場合は3月1日を誕生日として扱う
19+
if (bm === 2 && bd === 29 && m === 3 && d === 1 && !isLeapYear(y)) {
20+
return true;
21+
}
22+
23+
return m === bm && d === bd;
24+
}
25+
26+
function isLeapYear(year: number): boolean {
27+
return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
28+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* SPDX-FileCopyrightText: syuilo and misskey-project
3+
* SPDX-License-Identifier: AGPL-3.0-only
4+
*/
5+
6+
import * as Misskey from 'misskey-js';
7+
import { describe, test, expect } from 'vitest';
8+
import { isBirthday } from '@/utility/is-birthday.js';
9+
10+
describe('isBirthday', () => {
11+
test('通常の誕生日', () => {
12+
const currentDate = new Date('2024-05-15');
13+
const result = isBirthday({
14+
birthday: '2000-05-15',
15+
} as Misskey.entities.UserDetailed, currentDate);
16+
17+
expect(result).toBe(true);
18+
});
19+
20+
test('誕生日ではない場合', () => {
21+
const currentDate = new Date('2024-05-15');
22+
const result = isBirthday({
23+
birthday: '2000-06-20',
24+
} as Misskey.entities.UserDetailed, currentDate);
25+
26+
expect(result).toBe(false);
27+
});
28+
29+
test('平年に閏日生まれを見た際に3月1日を誕生日とする', () => {
30+
const currentDate = new Date('2023-03-01');
31+
const result = isBirthday({
32+
birthday: '2000-02-29',
33+
} as Misskey.entities.UserDetailed, currentDate);
34+
35+
expect(result).toBe(true);
36+
});
37+
38+
test('閏年に閏日生まれを見た際に2月29日を誕生日とする', () => {
39+
const currentDate = new Date('2024-02-29');
40+
const result = isBirthday({
41+
birthday: '2000-02-29',
42+
} as Misskey.entities.UserDetailed, currentDate);
43+
44+
expect(result).toBe(true);
45+
});
46+
47+
test('閏年に閏日生まれを見た際に3月1日を誕生日としない', () => {
48+
const currentDate = new Date('2024-03-01');
49+
const result = isBirthday({
50+
birthday: '2000-02-29',
51+
} as Misskey.entities.UserDetailed, currentDate);
52+
53+
expect(result).toBe(false);
54+
});
55+
});

0 commit comments

Comments
 (0)