class Time {
	static get ONE_HOUR() {
		return 3600000;
	}

	static get ONE_DAY() {
		return 86400000;
	}

	static get TIMEZONE_OFFSET() {
		return -(new Date().getTimezoneOffset() * 60 * 1000);
	}

	static getTimezoneOffset(date) {
		return -(date.getTimezoneOffset() * 60 * 1000);
	}

	static getTimezoneOffsetForLocalDayIndex(dayIndex) {
		return Time.getTimezoneOffset(new Date(dayIndex * Time.ONE_DAY));
	}

	/**
	 * Returns the index of the day of the given date.
	 * It is the index of the local time. So 1970-01-01 23:00:00 will return 0 in GMT+0 and 1 in GMT+1, GMT+2, etc...
	 */
	static getLocalDayIndex(date) {
		var localTimestamp = date.getTime() + Time.getTimezoneOffset(date);
		return Math.floor(localTimestamp / Time.ONE_DAY);
	}

	static getCurrentLocalDayIndex() {
		return Time.getLocalDayIndex(new Date());
	}

	static getTimestampForLocalDayIndex(dayIndex = null) {
		if (dayIndex === null) {
			dayIndex = Time.getCurrentLocalDayIndex();
		}

		return (dayIndex * Time.ONE_DAY) - Time.getTimezoneOffsetForLocalDayIndex(dayIndex);
	}

	static getDateForLocalDayIndex(dayIndex) {
		return new Date(Time.getTimestampForLocalDayIndex(dayIndex));
	}

	/**
	 * Retunrs the given milliseconds converted to a proper duration string.
	 */
	static formatDuration(milliseconds) {
		var hours = Math.floor(milliseconds / 1000 / 60 / 60);
		var minutes = Math.round((milliseconds - (hours * 60 * 60 * 1000)) / 1000 / 60);

		return (hours > 0 ? hours + "h" : "") + (hours > 0 && minutes > 0 ? " " : "") + (minutes > 0 ? minutes + "m" : "");
	}

	/**
	 * Retuns a string containig the date as a UNIX date string like "1970-01-01".
	 */
	static getUnixDate(date) {
		return date.getFullYear() + "-" + Time.addLeadingZero(date.getMonth() + 1) + "-" + Time.addLeadingZero(date.getDate());
	}

	/**
	 * Returns a date object representing the start of the last month.
	 */
	static getLastMonthStartDate() {
		var lastMonthStartDate = new Date();
		lastMonthStartDate.setHours(0);
		lastMonthStartDate.setMinutes(0);
		lastMonthStartDate.setSeconds(0);
		lastMonthStartDate.setMonth(lastMonthStartDate.getMonth() - 1);
		lastMonthStartDate.setDate(1);

		return lastMonthStartDate.getFullYear() + "-" + Time.addLeadingZero(lastMonthStartDate.getMonth() + 1) + "-" + Time.addLeadingZero(lastMonthStartDate.getDate());
	}

	/**
	 * Returns a date object representing the end of the last month.
	 */
	static getLastMonthEndDate() {
		var lastMonthEndDate = new Date();
		lastMonthEndDate.setHours(0);
		lastMonthEndDate.setMinutes(0);
		lastMonthEndDate.setSeconds(0);
		lastMonthEndDate.setDate(1);
		lastMonthEndDate.setSeconds(-1);

		return lastMonthEndDate.getFullYear() + "-" + Time.addLeadingZero(lastMonthEndDate.getMonth() + 1) + "-" + Time.addLeadingZero(lastMonthEndDate.getDate());
	}

	static addLeadingZero(value) {
		value = "" + value;
		if (value.length < 2) {
			value = "0" + value;
		}

		return value;
	}
}