【问题标题】:How to get future date based on timestamp ratio如何根据时间戳比率获取未来日期
【发布时间】:2021-10-01 09:46:00
【问题描述】:

我正在尝试为游戏创建一个虚拟日历。 我有一些事件会在现实中持续一段时间(1 周,1 个月)。 在游戏中,这些事件应始终等于 1 年。

为了简单起见,我的目标是使用 date-fns 并使用时间戳来保持比率。

假设我有一个活动持续 1 周(现实生活) 在1年的游戏中。 如果我尝试在 活动开始 + 3 天 时获取游戏中的日期(几乎一半的活动过去了)。从理论上讲,我应该在虚拟日历中接近 6 个月,但是在测试它时会在几年后给我一个答案。

import {
    addDays,
    addYears,
    getTime
} from "date-fns";

// Initiate Dates
const now = new Date()
const nextWeek = addDays(now, 7);
const nextYear = addYears(now, 1);
// Initiate Timestamp convertions
const currentTimestamp = getTime(now)
const tmrTimestamp = getTime(addDays(now, 3))
const nextWeekTimestamp = getTime(nextWeek)
// Calculate differences
const differenceReal = nextWeekTimestamp - currentTimestamp
const differenceVirtual = getTime(nextYear) - currentTimestamp
console.log(`difference_real : ${differenceReal}`)
console.log(`difference_virtual : ${differenceVirtual}`)
// Calculate the ratio
const ratio = differenceReal / differenceVirtual
// Log information
console.log(`ratio: ${ratio}`)
console.log(`ts_now ${getTime(now)}`)
console.log(`ts_tmr ${getTime(tmrTimestamp)}`)
//Calculate equivalence of day+1 on a year
const nextDayRatioed = tmrTimestamp / ratio
console.log(`ts_ratioed: ${Math.round(nextDayRatioed)}`)
console.log(`ts_next_year: ${getTime(nextYear)}`)
console.log(`next_year: ${nextYear.toLocaleString()}`)
console.log(`tmr_relative: ${new Date(Math.round(nextDayRatioed)).toLocaleString()}`)

输出:

我怎样才能让tmr_relative 成为正确的值,它或多或少是 2022 年 1 月

【问题讨论】:

    标签: javascript typescript date-fns


    【解决方案1】:

    你必须保持不变

    • 游戏的开始时间作为起点。
    • 您想要的时间比率。在您的情况下,1 周就是您的游戏的 1 年。

    检查以下方法以仅使用日期来实现。

    const ratio = 365/7;   //This is the virtual ration that you want
    const nowReal = new Date() //This would always be the basis to compare
    
    //Use a fixed date one week later to test how it would behave
    const nextWeekReal = new Date();
    nextWeekReal.setDate(nextWeekReal.getDate() + 7); 
    
    //Use a fixed date 2 week later to test how it would behave
    const doubleNextWeekReal = new Date();
    doubleNextWeekReal.setDate(doubleNextWeekReal.getDate() + 14); 
    
    //Check the next week virtual date
    console.log(virtualDate(nowReal, datediff(nowReal, nextWeekReal), ratio));
    
    //Check after 2 weeks the virtual date
    console.log(virtualDate(nowReal, datediff(nowReal, doubleNextWeekReal), ratio));
    
    
    function datediff(first: any, second: any) {
        // Take the difference between the dates and divide by milliseconds per day.
        // Round to nearest whole number to deal with DST.
        return Math.round((second-first)/(1000*60*60*24));
    }
    
    function virtualDate(basis: Date, diff: number, ration: number){
      const virtualDate = new Date();
      virtualDate.setDate(basis.getDate() + diff * ratio);
      return virtualDate;
    }
    

    结果考虑到您现在在 24/7/21 开始游戏。

    实时 1 周过去后,它会在 1 年后从原点打印您

    实时 2 周过去后,它将在 2 年后从原点打印您

    假设我有一个为期 1 周的活动(现实生活)在游戏中 将是 1 年。如果我在参加活动时尝试获取游戏内日期 开始 + 3 天(活动几乎过了一半)。理论上我 应该接近6个月

    //Use a fixed date half a week later to test how it would behave
    const halfWeekReal = new Date();
    halfWeekReal.setDate(halfWeekReal.getDate() + 3); 
    console.log("Half Week have passed in real time " + halfWeekReal);
    
    //Check after half week the virtual date
    console.log("Virtual date will be " + virtualDate(nowReal, 
    datediff(nowReal, halfWeekReal), ratio));
    

    这将打印出来

    大约5个月,这是你描述的正确行为。

    【讨论】:

    • 谢谢 我用它来构建一个处理虚拟日历的迷你库。你有 github 用户名,所以如果你愿意,我可以信任你吗? npmjs.com/package/calendar-virtual
    【解决方案2】:

    这是一个使用普通的老式 JS 的解决方案。

    let refInGameDate = new Date()
    document.querySelector('#days').addEventListener('change', e => {
      let days = +e.target.value
      let years = (Math.floor(days / 7) + (days % 7 / 7)).toFixed(2)
      document.querySelector('#ingame').innerText = years
      let rd = refInGameDate.getTime() + (years * 365 * 24 * 60 * 60 * 1000)
      document.querySelector('#indate').innerText = new Date(rd).toString();
    })
    <input type='number' id='days' /> real-time days
    <hr>
    <div>in-game translation: <span id='ingame'></span> years</div>
    <div>date representation: <span id='indate'></span></div>

    【讨论】:

    • 我想使用 date-fns,因为稍后我将使用许多更复杂的日期操作。此外,无论实时多长时间,它都应该始终等于游戏中的 1 年 1 week in real = 1 year in game 1 month in real = 1 year in game 这就是我试图获得比率的原因
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-06
    • 1970-01-01
    • 2020-11-02
    • 1970-01-01
    相关资源
    最近更新 更多