😑 cannot get system time when running locally😫

Any strategies for this? Any way form my code to switch on an environment var?

1 Like

Maybe query network time…

1 Like

There is only one Time.now() function. Are there system shared functions I can get to like msg.time or something like that?

1 Like

What msg.time means? the transactions signature created time?

Time.now() is the moment executing the canister function, I think it’s sufficient for most situations.

2 Likes

The IC does not provide any such functionality. Unfortunately, “system time” has no well-defined meaning in a distributed system. Plus, execution on the IC has to be deterministic across replicas. Hence, Time.now is the closest to “real” time that the platform can provide.

Running “locally” does not change that, since it is supposed to maintain all observable properties of the real network.

1 Like

So why then is it not doing so? When I call Time.now() from my motoko code on my local replica it errors out with the message in the title. Maybe this just needs to be implemented as a switch in dfx? Or in the Prim library shim for local replicas? It makes testing canisters locally very difficults. I was using it as a bit of chaos in a Hash calc so it is easy to route around for now with a nonce, but in the long run I’d like a bit less predictability.

1 Like

Actually, can you clarify what you mean by running “locally”?

Time.now() probably fails when run in the interpreter (probably with an ugly stacktrace), but should work on the emulator, local replica and full network.

I don’t know of any way to programmatically detect whether the code is running in the interpreter or a replica - perhaps we should add one. But the interpreter is really not meant for running production code, even for testing purposes. There are too many aspects of the IC that are not yet fully implemented in the interpreter (such as cycle management, state rollback on trap, etc).

1 Like

Ah, sorry, I think I misunderstood your question. By “running locally”, do you mean compiling with --no-system-api? Well, as the name indicates, that does not give access to any system functionality, and instead creates a pure Wasm module with no dependencies.

Ahhh…yes… you are right. This is failing while running tests:

$(shell vessel bin)/moc $(shell vessel sources) -wasi-system-api -o Test.wasm Test.mo && wasmtime Test.wasm

Any strategy for faking a time here? Or creating a mock?

1 Like

Hah! I actually forget about the wasi backend - I think we should be able to mock something for time there, but there’s lots of other stuff that doesn’t work on the wasi target (like actors).

A legitimate use of the wasi target (for now) is for testing libraries of non-IC functionality such as basic data structure libraries. That’s what bits of the motoko-base library are tested on.

2 Likes

Bumping for visibility - any update on getting system time to not throw and error when compiling w/moc locally? Or to at least return a “mock-able” result that would mimic time incrementing as execution of tests/other proceeds?

Would be awesome to be able to run/test this without deploying to the local replica each time.

You can do this but for a Time module.

In production provide something like this:

module {
  public func now() {
    Time.now();
  };
};

During testing provide something like this:

module {
  public func now() {
    // Return a hard coded time value
  };
};

This would work great, unless you are also running tests and expect the time value to increment for each new call. I don’t believe modules can hold state, so there would need to be another hacky workaround on top of the solution you provided.

In that case I think your only option might be to refactor your code to accept the current time as an argument

2 Likes