I am trying to have a virtual calendar for a game. I have events that will last a certain time in reality (1 week, 1 month). In the game those events should always be equal to 1 year.
To make things simple my goal was to use date-fns and work with timestamps to keep a ratio.
Lets say I have an event running for 1 week (real life) In game that would be 1 year. If I try to get the in-game date when I'm at event start + 3 days (almost half of the event passed). Theoretically I should be close to 6 months in the virtual calendar however while testing its gives me an answer years later.
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()}`)
Output:
How could I get the tmr_relative
to be the correct value which would be more or less January of 2022
You must keep as constant
Check the following way to achieve that using only date.
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;
}
Result considering that you start the game now on 24/7/21.
After 1 week have passed in real time it will print you 1 year later from the point of origin
After 2 weeks have passed in real time it will print you 2 years later from the point of origin
Lets say I have an event running for 1 week (real life) In game that would be 1 year. If I try to get the in-game date when I'm at event start + 3 days (almost half of the event passed). Theoretically I should be close to 6 months
//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));
This will print
It is about 5 months, which is the correct behavior you have described.