在前几天写的数据展示页面中,日历与JSON数据的时间处理依赖于本地时区的getDay()和setDate()方法。然而,博客部署在GitHub Pages,时区的不同导致日历出现了显示偏差

本地时间异常

涉及函数:getStartDate

原代码:

这里的getDay()和setDate()方法是基于Github本地时区,不细心

function getStartDate(today, daysOffset) {
    const currentDayOfWeek = today.getDay();
    const daysToMonday = (currentDayOfWeek === 0 ? 6 : currentDayOfWeek - 1); 
    const startDate = new Date(today);
    startDate.setDate(today.getDate() - daysToMonday - daysOffset); 
    startDate.setDate(startDate.getDate() - (startDate.getDay() === 0 ? 6 : startDate.getDay() - 1)); 
    return startDate;
}

改进后:

修改后:采用getUTCDay()和setUTCDate()方法,使用UTC时间来保证时间处理的一致性

function getStartDate(today, daysOffset) {
    const currentDayOfWeek = today.getUTC11Day();
    const daysToMonday = (currentDayOfWeek === 0 ? 6 : currentDayOfWeek - 1);
    const startDate = new Date(today);
    startDate.setUTCDate(today.getUTCDate() - daysToMonday - daysOffset);
    return startDate;
}

JSON数据与日历数据两者时区不一致


// 涉及函数:generateCalendar

// 原代码:

// 在与JSON日期数据进行比较时,由于时区问题,日历的显示存在错位

const todayStr = getChinaTime().toISOString().split('T')[0];
let currentDate = new Date(startDate);

// 改进后:

// 将currentDate时间归零,避免由于时区差异导致的日期比较错误

const todayStr = getChinaTime().toISOString().split('T')[0];
let currentDate = new Date(startDate);
currentDate.setUTCHours(0, 0, 0, 0);

日期显示与更新逻辑异常

涉及函数:createDayContainer

同上,本地时间异常

// 原代码:
dateNumber.innerText = date.getDate();

// 改进后
dateNumber.innerText = date.getUTCDate();

异步打字机时区异常

涉及函数:displayCalendar

同上,本地时间异常

// 原代码:
currentDate.setDate(currentDate.getDate() + 1);

// 改进后
currentDate.setUTCDate(currentDate.getUTCDate() + 1);

UPDATE 日历交互动画

1.默认显示当天日期,不显示球体

2.光标悬浮其他日历时,隐藏当天日期,显示球体,反之亦然

3.整体主题色为:rgb(36, 36, 40)

4.日历的所有日期下添加2px厚下划线

function createDayContainer(date, activities) {
    const dayContainer = document.createElement('div');
    dayContainer.className = 'day-container';

    const dateNumber = document.createElement('span');
    dateNumber.className = 'date-number';
    dateNumber.innerText = date.getUTCDate();
    dayContainer.appendChild(dateNumber);

    const activity = activities.find(activity => activity.activity_time === date.toISOString().split('T')[0]);
    // console.log(processedActivities);
    if (activity) processedActivities.push(activity);

    // 根据骑行距离设置球的大小
    const ballSize = activity ? Math.min(parseFloat(activity.riding_distance) / 4, 24) : 2;

    const ball = document.createElement('div');
    ball.className = 'activity-indicator';
    ball.style.width = `${ballSize}px`;
    ball.style.height = `${ballSize}px`;
    if (!activity) ball.classList.add('no-activity');
    ball.style.left = '50%';
    ball.style.top = '50%';
    dayContainer.appendChild(ball);

    dayContainer.addEventListener('mouseenter', () => {
        if (date.toDateString() === new Date().toDateString()) {
            dateNumber.style.opacity = '0';
            ball.style.opacity = '1';
        } else {
            if (todayContainer) {
                todayContainer.querySelector('.date-number').style.opacity = '0';
                todayContainer.querySelector('.activity-indicator').style.opacity = '1';
            }
        }
    });
    dayContainer.addEventListener('mouseleave', () => {
        if (date.toDateString() === new Date().toDateString()) {
            dateNumber.style.opacity = '1';
            ball.style.opacity = '0';
        } else {
            if (todayContainer) {
                todayContainer.querySelector('.date-number').style.opacity = '1';
                todayContainer.querySelector('.activity-indicator').style.opacity = '0';
            }
        }
    });

    if (date.toDateString() === new Date().toDateString()) {
        todayContainer = dayContainer;
        dayContainer.classList.add('today');
        ball.style.backgroundColor = '#242428';
        dateNumber.style.color = '#242428';
        dateNumber.style.opacity = '1';
        ball.style.opacity = '0';
    }
    return dayContainer;
}