Start learning free

LESSON 165 OF 173 · BACKEND: BACKEND WITH AI

Dates the AI Got Wrong

Practice

An AI assistant wrote GET /orders?since=… for the shop: the orders placed on or after a date. Customers type the date day first, like 18/04/2026. The database keeps each order's date year first, like 2026-04-18. C# has no >= for strings, so the AI compared the two texts with string.CompareOrdinal:

app.MapGet("/orders", (HttpRequest request) => {
    string since = request.Query["since"];
    var cmd = db.CreateCommand();
    cmd.CommandText = "SELECT * FROM orders";
    using var reader = cmd.ExecuteReader();
    var result = new List<Dictionary<string, object>>();
    while (reader.Read()) {
        if (string.CompareOrdinal((string)reader["ordered"], since) >= 0) {
            result.Add(RowToDict(reader));
        }
    }
    return Results.Json(result);
});

CompareOrdinal compares strings character by character, and the first difference decides. "2026-03-02" comes after "18/04/2026", because "2" comes after "1". So since=18/04/2026 answered all 7 orders and since=30/04/2026 answered none. The impossible 31/04/2026 got 200 and an empty list, and a request without since got all 7 orders.

The fix: turn each text into a real date, then compare dates. DateTime.ParseExact(text, format, CultureInfo.InvariantCulture) reads a text the way the format describes. In a format, dd is the day, MM the month (capital: mm means minutes) and yyyy the four-digit year. ParseExact throws on a text that doesn't fit; DateTime.TryParseExact gives false instead, for a text that doesn't fit and for a day that doesn't exist, and puts the date in an out variable:

using System.Globalization;

var d = DateTime.ParseExact("07/05/2026", "dd/MM/yyyy", CultureInfo.InvariantCulture);
Console.WriteLine($"{d.Day} {d.Month} {d.Year}");   // 7 5 2026
var ok = DateTime.TryParseExact("30/02/2026", "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out var bad);
Console.WriteLine(ok);                                // False: there is no 30 February

The requests and the answers your route must give:

GET /orders?since=18/04/2026  →  200  [{"customer_id": 3, "id": 4, "ordered": "2026-04-18", "status": "shipped"}, …]   (orders 4 to 7)
GET /orders?since=30/04/2026  →  200  [{"customer_id": 4, "id": 5, "ordered": "2026-05-07", "status": "paid"}, …]   (orders 5 to 7)
GET /orders?since=01/06/2026  →  200  []
GET /orders?since=31/04/2026  →  400  {"error": "since must be a date like 18/04/2026"}
GET /orders  →  400  {"error": "since must be a date like 18/04/2026"}

Your task: rewrite the MapGet function of /orders. Read since with TryParseExact and the format "dd/MM/yyyy", and answer 400 with the error when it isn't a date. Read each order's ordered with "yyyy-MM-dd", and answer the orders placed on or after since.


Assignment
Follow the Coding Tutorial to rewrite the /orders route so it compares real dates instead of texts.


Hint
TryParseExact gives false for a wrong date and for a missing one, so one if covers both. Write the month as capital MM. Use >= so an order placed on the since day itself is kept.


STEP 1 OF 11
    Ctrl + Enter to check