# Why LLMs get dates and times wrong (and how to fix it)

You can hand an agent a perfectly accurate clock and it still can't reason from it. What building a scheduling agent taught us about time, and the fixes that worked.

You can hand an agent a perfectly accurate clock and it still can't reason from it. What building our Slack and Teams scheduling agent taught us about time, and the fixes that actually worked.

Models can reason their way through complex problems, yet ours couldn't reliably work out that a 9am meeting had already happened.

That surprised us. In building our Slack and Teams Scheduling Agent, a lot "just worked" by leveraging our temporal infrastructure. All the things needed for the full scheduling lifecycle were ready to go. Most of the difficulty lay in helping the agent understand the concept of time.

Straight out of the box, LLMs contain no concept of time. Well they might, but that is at best locked to when the model's training and refinement ended. So you start with telling the agent when "now" is by adding it to the prompt. This resolves a large number of issues: "next Tuesday" starts tracking correctly. Given the anchor of the current time, the model can then reason about a number of things.

A number of things, but not everything.

## Knowing the time and reasoning about it are different skills

When given the current time, ask the agent "what do I have scheduled today" and it knows what "today" is. It can invoke a tool that can provide an agenda for a given date. But given the day's events, each with a perfectly good timestamp matching your API, it cannot reliably tell you that the 9am is in the past when it is now 11am.

It turns out that even with billions of parameters at its disposal, reasoning about where "now" sits among a list of times is hard.

It helps to think of the models as closer to human than machine. Most people don't see ISO8601 formatted strings every day, let alone one including an offset and a time zone name. That may be the richest format for a machine, but it's close to gibberish to a human.

Your average person would take a good guess at what such a string meant and be right most of the time. The same applies to LLMs. But we expect and need machines to be correct all the time, not most of the time.

The problem is you cannot prove any of this. That's the amazing and frustrating nature of working with agents. But our experimentation has guided us towards thinking of models as more human-like than machine-like, and the correctness of our agent's behavior has increased as we've applied that.

A model can be told the time, so that it knows the time in the sense that it can read it back to you. But it can't always reason about other, relative times.

Providing the current time adds knowledge. But when reasoning is then required results are still hit-and-miss.

## Don't make the model derive what you can hand it

One fix, the question of relative times, was not to coax better reasoning out of the model. It was to stop asking it to reason at all.

We added a field to our tool response that tells the model, explicitly, whether each event is in the past, in progress, or in the future. In code that's a trivial computation. We'd been leaving it to the model to derive, which turned an easy calculation into something requiring time-aware reasoning. Something easy to compute and hard to reason about became a simple label the model can use.

That turns out to be the general lesson, the one that travels beyond calendars. Anything the model would have to *calculate* from raw data is a candidate for labeling and handing over. Models are poor calculators wearing a very convincing disguise. Many such wins have come from the same approach: work out the reasoning that was needed but unreliable, and work out how to eliminate it.

## The model and the human have to be looking at the same thing

We learned a different flavor of this when we took date formatting away from the model. It had been rendering dates and times for users, and doing it badly. A scheduling agent can't handle or render time with any inaccuracy, it undermines the whole experience. So we moved that job into our own code, where we could control it. But it had a consequence we didn't see coming.

With formatting handled elsewhere, the model now only saw raw UTC timestamps. As it did not need to reason about them to show the user, it no longer "saw" what the user did. The localized, human-shaped version "Thursday at 11am" was invisible. So when a user said "Thursday at eleven," the model had to map that phrase onto one of the UTC strings in the list we'd handed it. Making that jump was very unreliable. In resolving one problem, we'd increased the amount of reasoning needed in an adjacent area.

If it had simply been getting the time zone math wrong, we'd have seen a consistent offset, e.g. errors would be consistently out by an hour. But we didn't. It would pick the wrong day, or a time several hours adrift, with no pattern we could see. To all intents and purposes it looked like it was guessing. When faced with a list of opaque timestamps and a human phrase that didn't visibly correspond to any of them, it pattern-matched, badly. The same kind of failure as the 9am meeting, but in a more subtle guise.

The fix was the same move as before, made symmetric. Our tool result already required a time zone. For each available slot, it now returns both the UTC string the model must submit *and* a locally formatted label that matches what a human would actually say. The model sees the value it needs to use right next to the value close to what a person is likely to say. It no longer has to bridge the two in its head, we've joined the dots and reduced the reasoning required.

The first example was about not making the model compute. This one is about not making it translate between the form a machine acts on and the form a human speaks. Same root cause underneath: a gap between the shape of the data and the shape the model needs, which we always start from hoping it would close on its own.

## The cost of being too precise

With more context being better, we looked to reduce another source of calculation required. On top of "past", "active", and "future" we provided "seconds until start time" with positive values for future events, negative for past ones. Easy to calculate, enriched context.

However, our agent started saying things like "it's 4 hours and 24 minutes until your meeting."

No human talks like that. You'd say "in a few hours" or "this afternoon". The model wasn't wrong, it just felt weird. Sometimes that's almost as bad. We seemed to have a part to play in this. The precision of the input appeared to reflect in the precision of the output.

Anyone who has estimated software will recognize the instinct. You say a piece of work is "a couple of weeks", not "eleven days". You size it as a two, not as 5.5 hours. Not because you can't be more precise, but because the looseness itself is the information. The unit brings an implied accuracy for things like an estimate. We reach for the higher unit deliberately, to signal how confident we are.

Granularity carries certainty. Hand the model a figure accurate to the second and you've stripped that signal out. It can't be appropriately vague, because nothing in the input told it vagueness was allowed.

We're still working out how best to tackle this. Richer prompts for explaining relative times and altering how the relative duration is returned both work to varying degrees. Essentially, instruct the agent how vague to be, or provide it with more vague context. The former feels better, giving the agent "lossless" data, but LLMs don't care about your feelings.

## Deciding what not to ask

Building a good agent is as much about deciding what not to ask it to do as it is what it should do. We started out leaving as much as we could to the model. Now we've ended up giving it less to figure out, and being careful about the shape of what's left. Tell it the time, by all means. But the moment you expect it to reason from there, you're the one doing the thinking. Including, it turns out, how precise it's allowed to be.