Log In  


The date() function returns a formatted date.

It takes three arguments

  1. format, the format to use for display (See: Programming in Lua 22.1 - Date and Time). Starting the format with ! makes it UTC, otherwise it will be local time.
  2. t, the timestamp either as a string (in the default UTC YYYY-mm-dd HH:MM:SS) or Unix timestamp (seconds since 1970-01-01 00:00:00)
  3. delta, an amount of seconds to add to the timestamp.

date() gets the current time in UTC, and is used to generate timestamps in Picotron (for modified and created times).

date("%Y-%m-%d %H:%M:%S", timestamp) converts timestamp to local time. (So you can store timestamps in UTC and later display them in local time)

date(nil, nil, -86400 * 10) subtracts 10 days from the current time.

Since timestamps are in YYYY-mm-dd HH:MM:SS format, they can be compared directly as strings.

Example: "2025-01-17 05:00:00" < "2025-01-17 05:10:00" returns true, as the first timestamp is smaller than the second timestamp (by 10 minutes).

I did not realize timestamps could be compared as strings until after writing a function to parse timestamps into Unix timestamps lol.

Here is the function to do that. It takes a timestamp string (from date), and returns the Unix timestamp. You can convert a Unix timestamp back into a string using date. Not sure if there are many practical uses for this, since you can do most things with date directly, but I'm sure it'll be useful for something.

--- Converts a Picotron timestamp (from date()) to a unix timestamp
--- @param d string
function DateToUnix(d)
	local start, _, year, month, day, hour, minute, second = d:find("(%d+)%-(%d+)%-(%d+) (%d+):(%d+):(%d+)")
	if start then
		local tm_year = tonum(year) - 1900
		local month = tonum(month)
		local day = tonum(day)
		local tm_hour = tonum(hour)
		local tm_min = tonum(minute)
		local tm_sec = tonum(second)

		-- tm_yday is the number of days since jan 1
		-- the current day is not included, as it's not finished
		local tm_yday = -1

		local isLeapYear = ((year % 4 == 0) and (year % 100 ~= 0)) or (year % 400 == 0)
		for m = 1, month - 1, 1 do
			if m == 2 then
				tm_yday += isLeapYear and 29 or 28
			elseif m == 4 or m == 6 or m == 9 or m == 11 then
				tm_yday += 30
			else
				tm_yday += 31
			end
		end	
		tm_yday += day

		-- https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16
		return tm_sec + tm_min * 60 + tm_hour * 3600 + tm_yday * 86400 +
			(tm_year - 70) * 31536000 + ((tm_year - 69) // 4) * 86400 -
			((tm_year - 1) // 100) * 86400 + ((tm_year + 299) // 400) * 86400
	end

	return nil
end

I also made a quick function that uses the Unix timestamps to calculate the UTC offset (I don't think there's a direct way to do this using date, but I could be wrong.)

--- Calculates the timezone difference between local time and UTC
--- Add to UTC to get local time, subtract from local time to get UTC
function GetTZDiff()
	local utc = DateToUnix(date())
	local ltz = DateToUnix(date("%Y-%m-%d %H:%M:%S"))

	return ltz - utc
end

1


1

Thanks for this. I'm working with the date() function for a once-a-day trading card mechanic and to reset mineable asteroids every day in my Picotron space sim. However, I am still trying to figure out the best way to add 1000 years to the current UTC for displaying the date and time like they do in Elite Dangerous. Adding 31,556,952,000 seconds to the date seems ... odd oO;


@donswelt Have you considered just changing the year? Get just the year + 1000, and combine it with the rest of the date.

tonum(date("!%Y")) + 1000 .. date("!-%m-%d %H:%M:%S")

Or get the 2 digit year with a 30 in the front (will roll over after 2099)

date("!30%y-%m-%d %H:%M:%S")

1

@arnaught

> Or get the 2 digit year with a 30 in the front (will roll over after 2099)

I'll take my chances when it comes to Y3K bugs :D
Thanks, it's so easy, somehow I was blind to it.



[Please log in to post a comment]