How to make a date/time system with a fast forward feature?

I was thinking about a system as can be seen in games such as The Sims, SimCity, Cities: Skylines, Europa Universalis, etc. It is for an population/economy simulator. The date shall constantly be displayed in a corner. As the NPCs are supposed to age over time, they need to interact with it as well (birthday event).

My attempt is shown below but I am convinced it is really bad (i.e. months only have 31 days). Most other scripts stop running when time runs too fast.

Instead of fixing it, I would prefer to completely rewrite it. Maybe with invoke repeat to avoid the Update method?

Thanks for your help!

`

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.UI;

public class dayCycle : MonoBehaviour {

public float time;
public TimeSpan currentTime;
public Text timeText;
public static int years;
public static int months;
public static int days;
public static int hours;
public float minutes;
public static int timeSpeed;
public static int speed;

// Use this for initialization
void Start () {
    days = 0;
    months = 1;
    years = 2100;
    timeSpeed = 1;
    speed = 16;
}

// Update is called once per frame
void Update ()
{
    ChangeTime();
    if (Input.GetKeyDown(KeyCode.KeypadPlus))
    {
        timeSpeed = timeSpeed + 1;
    }
    if (timeSpeed > 2)
    {
        timeSpeed = 2;
    }
    if (Input.GetKeyDown(KeyCode.KeypadMinus))
    {
        timeSpeed = timeSpeed - 1;
    }
    if (timeSpeed < 0)
    {
        timeSpeed = 0;
    }
}
public void ChangeTime()
{
    time += Time.deltaTime * speed;
    if (time >= 1 && timeSpeed == 0)
    {
        minutes += 1;
        time = 0;
    }
    else if (time >= 1 && timeSpeed == 1)
    {
        minutes = 1 / 60;
        hours += 1;
        time = 0;
    }
    else if (time >= 1 && timeSpeed == 2)
    {
        minutes = 1 / 1440;
        hours = 1 / 24;
        days += 1;
        time = 0;
    }
    if (minutes == 60 && timeSpeed == 0)
    {
        hours += 0;
        minutes = 0;
    }
    if (hours == 24)
    {
        days += 1;
        hours = 1;
    }
    if (days == 32)
    {
        months += 1;
        days = 1;
    }
    if (months == 13)
    {
        years += 1;
        months = 1;
    }

    currentTime = TimeSpan.FromSeconds(time);
    timeText.text = years + "y " + months + "m " + days + "days " + hours + "h " + minutes + "min";
}
}

`

.NET already has very robust and mature date and time handling builtin. e.g. the DateTime structure. It has functions to add/subtract lengths of time, compare DateTimes, etc, and can pretty much do everything you want.

Fast Forwarding with this structure would be as simple as using a float multiplier.

I improved the first version and now created a complete date system outside of the .NET DateTime structure. It recognizes leap years, fast forwards minutes, hours, days, and is easy to access.

`

using UnityEngine;
using UnityEngine.UI;

public class DateTimeManager : MonoBehaviour
{
public float timeScale;
public int timeMode;
public int startHour, startDay, startMonth, startYear;
public string monthName;    
public bool am, noonAm, leapYear;
private Text calendarText;
public double minute, hour, day, second, month;
public int year;

void Start()
{
    startHour = 6;
    startDay = 15;
    startMonth = 07;
    startYear = 2017;
    year = startYear;
    month = startMonth;
    day = startDay;
    hour = startHour;
    year = startYear;

    timeMode = 1; //mode 2 and 3 for fast forwarding hours and days respectively
    timeScale = 200.0f; //change time speed: 200 = one hour takes 18 seconds
    am = true;
    noonAm = false; //true = noon is AM; option for 12 am/pm confusion

    calendarText = GameObject.Find("Calendar").GetComponent<Text>(); //create text box "Calendar" in Unity
    DetermineMonth();
}

void Update()
{
    CalculateTime();

}

//for UI
void TextCallFunction()
{
    // minutes included
    if (timeMode == 1)
    {
        if (am == true)
        {
            if (hour <= 9) //single digit hours get a 0
            {
                if (minute <= 9)
                {
                    calendarText.text = monthName + " " + day + " " + year + " " + "0" + hour + ":0" + minute + " AM";
                }
                else
                {
                    calendarText.text = monthName + " " + day + " " + year + " " + "0" + hour + ":" + minute + " AM";
                }
            }
            else if (minute <= 9)
            {
                calendarText.text = monthName + " " + day + " " + year + " " + hour + ":0" + minute + " AM";

                if (noonAm == false && hour == 12)
                {
                    calendarText.text = monthName + " " + day + " " + year + " " + hour + ":0" + minute + " PM";
                }
            }
            else
            {
                calendarText.text = monthName + " " + day + " " + year + " " + hour + ":" + minute + " AM";

                if (noonAm == false && hour == 12)
                {
                    calendarText.text = monthName + " " + day + " " + year + " " + hour + ":" + minute + " PM";
                }
            }
        }
        else if (am == false)
        {
            if (hour <= 9)
            {
                if (minute <= 9)
                {
                    calendarText.text = monthName + " " + day + " " + year + " " + "0" + hour + ":0" + minute + " PM";
                }
                else
                {
                    calendarText.text = monthName + " " + day + " " + year + " " + "0" + hour + ":" + minute + " PM";
                }
            }
            else
            {
                if (minute <= 9)
                {
                    calendarText.text = monthName + " " + day + " " + year + " " + hour + ":0" + minute + " PM";

                    if (noonAm == false && hour == 12)
                    {
                        calendarText.text = monthName + " " + day + " " + year + " " + hour + ":0" + minute + " AM";
                    }
                }
                else
                {
                    calendarText.text = monthName + " " + day + " " + year + " " + hour + ":" + minute + " PM";

                    if (noonAm == false && hour == 12)
                    {
                        calendarText.text = monthName + " " + day + " " + year + " " + hour + ":" + minute + " AM";
                    }
                }
            }
        }
    }

    //minutes excluded
    else if (timeMode == 2)
    {
        if (am == true)
        {
            calendarText.text = monthName + " " + day + " " + year + " " + hour + " AM";

            if (noonAm == false && hour == 12)
            {
                calendarText.text = monthName + " " + day + " " + year + " " + hour + " PM";
            }
        }
        else if (am == false)
        {
            calendarText.text = monthName + " " + day + " " + year + " " + hour + " PM";

            if (noonAm == false && hour == 12)
            {
                calendarText.text = monthName + " " + day + " " + year + " " + hour + " AM";
            }
        }
    }
    
    //hours excluded
    else if (timeMode == 3)
    {
        calendarText.text = monthName + " " + day + " " + year; 
    }
}

//determining month names
void DetermineMonth()
{
    if (month == 1)
    {
        monthName = "Jan";
    }
    if (month == 2)
    {
        monthName = "Feb";
    }
    if (month == 3)
    {
        monthName = "Mar";
    }
    if (month == 4)
    {
        monthName = "Apr";
    }
    if (month == 5)
    {
        monthName = "May";
    }
    if (month == 6)
    {
        monthName = "Jun";
    }
    if (month == 7)
    {
        monthName = "Jul";
    }
    if (month == 8)
    {
        monthName = "Aug";
    }
    if (month == 9)
    {
        monthName = "Sep";
    }
    if (month == 10)
    {
        monthName = "Oct";
    }
    if (month == 11)
    {
        monthName = "Nov";
    }
    if (month == 12)
    {
        monthName = "Dec";
    }

    TextCallFunction();
}

//determining total days in a month and leap years
void CalculateMonthLength()
{
    if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
    {
        if (day >= 32)
        {
            month++;
            day = 1;
            DetermineMonth();
        }
    }

    if (month == 2)
    {
        if (day >= 29)
        {
            //leap year
            if (year % 4 == 0 && year % 100 != 0)
            {
                TextCallFunction();
                DetermineMonth();
                leapYear = true;
            }
            if (leapYear == false)
            {
                month++;
                day = 1;
                DetermineMonth();
            }
            else if (day == 30)
            {
                month++;
                day = 1;
                DetermineMonth();
            }
        }

        if (month == 4 || month == 6 || month == 9 || month == 11)
        {
            if (day >= 31)
            {
                month++;
                day = 1;
                DetermineMonth();
            }
        }
    }
}

//time counter
void CalculateTime()
{

    if (timeMode == 1)
    {
        second += Time.fixedDeltaTime * timeScale;
        if (second >= 60)
        {
            minute++;
            second = 0;
            TextCallFunction();
        }

        else if (minute >= 60)
        {
            if (hour <= 12 && am == true)
            {
                hour++;

                if (hour >= 13)
                {
                    am = false;
                    hour = 1;
                }
            }
            else if (hour <= 12 && am == false)
            {
                hour++;

                if (hour == 12)
                {
                    day++;
                }
                else if (hour >= 13)
                {
                    hour = 1;
                    am = true;
                }
            }

            minute = 0;
            TextCallFunction();
        }
        else if (day >= 28)
        {
            CalculateMonthLength();
        }

        else if (month >= 12)
        {
            month = 1;
            year++;
            DetermineMonth();
        }
    }

    else if (timeMode == 2)
    {
        minute++;
        timeScale = 1;

        if (second >= 60)
        {
            minute++;
            second = 0;
            TextCallFunction();
        }

        else if (minute >= 60)
        {
            if (hour <= 12 && am == true)
            {
                hour++;

                if (hour >= 13)
                {
                    am = false;
                    hour = 1;
                }
            }
            else if (hour <= 12 && am == false)
            {
                hour++;

                if (hour == 12)
                {
                    day++;
                }
                else if (hour >= 13)
                {
                    hour = 1;
                    am = true;
                }
            }

            minute = 0;
            TextCallFunction();
        }
        else if (day >= 28)
        {
            CalculateMonthLength();
        }

        else if (month >= 12)
        {
            month = 1;
            year++;
            DetermineMonth();
        }
    }
    else if (timeMode == 3)
    {
        second += Time.fixedDeltaTime * timeScale;
        timeScale = 1;

        if (second >= 0.4f)
        {
            day++;
            second = 0;
            DetermineMonth();
        }
        else if (day >= 28)
        {
            CalculateMonthLength();
            DetermineMonth();
        }

        else if (month >= 12)
        {
            month = 1;
            year++;
            DetermineMonth();
        }
    }            
}
}

`