GameMaker: Formatted date output

(click to interact)

This is a small post about a replica of the strftime function seen in PHP, C standard library, and a handful of other APIs. Such a function takes a date-time and prints it according to the given format string.

The script supports the common formats and those that mapped reasonably to GML functions.

The idea

Nothing particular to this - you loop over the string, and if you encounter a %, you add the section up from start and up until the point, parse the next character, add one or other bit based on what the character is after % is, and move the start position.

The code

Nothing particular here either, so we're going to have this small script that pads a string/value to specified length, called string_lpad,

/// string_lpad(value, fill, len)
var s = string(argument0);
var p = argument1;
return string_repeat(p, ceil((argument2 - string_length(s)) / string_length(p))) + s;

And then the big script for the actual parsing,

/// date_format(datetime, format)
var start = 1;
var t = argument0;
var fmt = argument1;
var pos = 1;
var len = string_length(fmt);
var out = "", i, s;
while (pos <= len) if (string_ord_at(fmt, pos) == ord("%")) {
    if (pos > start) out += string_copy(fmt, start, pos - start);
    switch (string_ord_at(fmt, pos + 1)) {
        // time:
        case ord("I"): // HH, 12-hour
            i = date_get_hour(t) % 12;
            if (i == 0) i = 12;
            out += string_lpad(i, "0", 2);
            break;
        case ord("p"): // AM/PM
            i = date_get_hour(t);
            if (i >= 12) out += "PM"; else out += "AM";
            break;
        case ord("H"): // HH, 24-hour
            out += string_lpad(date_get_hour(t), "0", 2);
            break;
        case ord("M"): // MM
            out += string_lpad(date_get_minute(t), "0", 2);
            break;
        case ord("S"): // SS
            out += string_lpad(date_get_second(t), "0", 2);
            break;
        // date:
        case ord("y"): // YY
            out += string_lpad(date_get_year(t) % 100, "0", 2);
            break;
        case ord("Y"): // full year
            out += string(date_get_year(t));
            break;
        case ord("C"): // century
            out += string_lpad(date_get_year(t) div 100, "0", 2);
            break;
        case ord("m"): // month
            out += string_lpad(date_get_month(t), "0", 2);
            break;
        case ord("d"): // day of the month (0-padded)
            out += string_lpad(date_get_day(t), "0", 2);
            break;
        case ord("e"): // day of the month (space-padded)
            out += string_lpad(date_get_day(t), " ", 2);
            break;
        case ord("w"): // day of the week (0..7, starting Sunday)
            out += string(date_get_weekday(t));
            break;
        case ord("u"): // day of the week (1..7, starting Monday)
            i = date_get_weekday(t);
            if (i == 0) i = 7;
            out += string(i);
            break;
        case ord("j"): // day of the year (000...366)
            out += string_lpad(date_get_day_of_year(t), "0", 3);
            break;
        // shortcuts:
        case ord("D"): // MM/DD/YY
            out += string_lpad(date_get_month(t), "0", 2)
                + "/" + string_lpad(date_get_day(t), "0", 2)
                + "/" + string_lpad(date_get_year(t) % 100, "0", 2);
            break;
        case ord("F"): // YYYY-MM-DD
            out += string(date_get_year(t))
                + "-" + string_lpad(date_get_month(t), "0", 2)
                + "-" + string_lpad(date_get_day(t), "0", 2);
            break;
        case ord("r"): // 12-hour time
            i = date_get_hour(t);
            if (i >= 12) s = "PM"; else s = "AM";
            i = i % 12; if (i == 0) i = 12;
            out += string_lpad(i, "0", 2)
                + ":" + string_lpad(date_get_minute(t), "0", 2)
                + ":" + string_lpad(date_get_second(t), "0", 2)
                + " " + s;
            break;
        case ord("R"): // 24-hour time (HH:MM)
            out += string_lpad(date_get_hour(t), "0", 2)
                + ":" + string_lpad(date_get_minute(t), "0", 2);
            break;
        case ord("T"): // ISO 8601 time (HH:MM:SS)
            out += string_lpad(date_get_hour(t), "0", 2)
                + ":" + string_lpad(date_get_minute(t), "0", 2)
                + ":" + string_lpad(date_get_second(t), "0", 2);
            break;
        // general locale:
        case ord("a"): // short weekday name
            switch (date_get_weekday(t)) {
                case 1: s = "Mon"; break;
                case 2: s = "Tue"; break;
                case 3: s = "Wen"; break;
                case 4: s = "Thu"; break;
                case 5: s = "Fri"; break;
                case 6: s = "Sat"; break;
                default:s = "Sun"; break;
            }
            out += s;
            break;
        case ord("A"): // full weekday name
            switch (date_get_weekday(t)) {
                case 1: s = "Monday"; break;
                case 2: s = "Tuesday"; break;
                case 3: s = "Wednesday"; break;
                case 4: s = "Thursday"; break;
                case 5: s = "Friday"; break;
                case 6: s = "Saturday"; break;
                default:s = "Sunday"; break;
            }
            out += s;
            break;
        case ord("b"): case ord("h"): // short month name
            switch (date_get_month(t)) {
                case  1: s = "Jan"; break;
                case  2: s = "Feb"; break;
                case  3: s = "Mar"; break;
                case  4: s = "Apr"; break;
                case  5: s = "May"; break;
                case  6: s = "Jun"; break;
                case  7: s = "Jul"; break;
                case  8: s = "Aug"; break;
                case  9: s = "Sep"; break;
                case 10: s = "Oct"; break;
                case 11: s = "Nov"; break;
                case 12: s = "Dec"; break;
                default: s = "???"; break;
            }
            out += s;
            break;
        case ord("B"): // full month name
            switch (date_get_month(t)) {
                case  1: s = "January"; break;
                case  2: s = "February"; break;
                case  3: s = "March"; break;
                case  4: s = "April"; break;
                case  5: s = "May"; break;
                case  6: s = "June"; break;
                case  7: s = "July"; break;
                case  8: s = "August"; break;
                case  9: s = "September"; break;
                case 10: s = "October"; break;
                case 11: s = "November"; break;
                case 12: s = "December"; break;
                default: s = "Unknown"; break;
            }
            out += s;
            break;
        // locale-specific:
        case ord("x"): // ls date
            out += date_date_string(t);
            break;
        case ord("X"): // ls time
            out += date_time_string(t);
            break;
        case ord("c"): // ls datetime
            out += date_datetime_string(t);
            break;
        // misc:
        case ord("%"): out += "%"; break;
        case ord("n"): out += chr(10); break;
        case ord("t"): out += chr(9); break;
        //
        default: out += string_copy(fmt, pos, 2);
    }
    pos += 2;
    start = pos;
} else pos++;
if (pos > start) out += string_copy(fmt, start, pos - start);
return out;

Related posts:

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.