Getting time in a specific timezone

Good follow-up. Let’s do timezone handling first, then the time-lock question.

Getting time in a specific timezone

C++20 (<chrono> with time zone database) — the modern, correct way

#include <iostream>
#include <chrono>

int main() {
    using namespace std::chrono;

    auto now = system_clock::now();

    // Convert to specific timezones using IANA names
    auto tokyoTime = zoned_time{"Asia/Tokyo", now};
    auto nyTime    = zoned_time{"America/New_York", now};

    std::cout << "UTC:      " << now << "\n";
    std::cout << "Tokyo:    " << tokyoTime << "\n";
    std::cout << "New York: " << nyTime << "\n";

    return 0;
}

Output (example):

UTC:      2026-09-01 05:34:12.123456
Tokyo:    2026-09-01 14:34:12.123456 JST
New York: 2026-09-01 01:34:12.123456 EDT

Note: this correctly handles daylight saving time automatically — New York shows EDT or EST depending on the date. On Linux (Ubuntu) this works out of the box using the system’s IANA tzdata. On Windows, GCC/Clang need the tzdata bundled or downloaded (MSVC’s implementation handles this itself); if your compiler’s <chrono> doesn’t have full timezone DB support yet, the fallback below works everywhere.

Portable fallback (C and C++, any compiler) — using the TZ environment variable

This works because localtime() respects the TZ env var, which you can change at runtime:

#include <iostream>
#include <ctime>
#include <cstdlib>

void printTimeInZone(const char* tz, const char* label) {
#ifdef _WIN32
    _putenv_s("TZ", tz);
    _tzset();
#else
    setenv("TZ", tz, 1);
    tzset();
#endif
    std::time_t now = std::time(nullptr);
    char buf[64];
    std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", std::localtime(&now));
    std::cout << label << ": " << buf << "\n";
}

int main() {
    // On Linux: IANA names work directly
    printTimeInZone("Asia/Tokyo", "Tokyo");
    printTimeInZone("America/New_York", "New York");

    // On Windows (older CRT): TZ format is POSIX-style, e.g. "JST-9" or "EST5EDT,M3.2.0,M11.1.0"
    // Windows 10+ CRT (VS 2019+) actually accepts IANA names too if the OS has the ICU/tzdata support enabled.

    return 0;
}

Output:

Tokyo: 2026-09-01 14:34:12 JST
New York: 2026-09-01 01:34:12 EDT

A practical tip: don’t hardcode UTC offsets (e.g. +9) for Tokyo/NY — Tokyo has no DST so it’s always UTC+9, but New York shifts between UTC-5 and UTC-4. Always use a timezone-aware library/API rather than manual offset math, or you’ll get an hour wrong for half the year.

Preventing users from changing the system time/timezone on Windows

This is a legitimate ask for things like license/trial-period enforcement (blocking clock-rollback attacks), kiosk mode, or corporate compliance — Windows gives you a few real mechanisms, layered:

1. Remove the privilege that allows changing system time

Changing the system clock requires SeSystemtimePrivilege. A standard (non-admin) user doesn’t have it by default, but if your concern is admin users too, you can restrict it via Local Security Policy (secpol.msc → Local Policies → User Rights Assignment → “Change the system time”) — remove all users/groups from that list. This is a policy change, not something you’d do from your app’s code directly, but you can automate it via ntrights.exe/PowerShell as part of an installer:

# Example: remove a user from the "Change the system time" privilege via secedit
# (typically scripted as part of deployment, not runtime app code)

2. Detect and respond to time/timezone changes at runtime

Since you can’t always fully lock this down (a determined local admin can usually re-grant themselves the privilege), a robust design also detects tampering and reacts — this is actually the more reliable strategy for something like license enforcement:

#include <windows.h>
#include <iostream>

// React to WM_TIMECHANGE, sent to all top-level windows when system time/timezone changes
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    if (msg == WM_TIMECHANGE) {
        std::wcout << L"System time or timezone was changed!\n";
        // Re-validate license expiry, log the event, force re-auth, etc.
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

3. Detect clock rollback for license/trial enforcement specifically

The strongest pattern for anti-rollback isn’t blocking the OS clock at all — it’s storing a monotonic reference point the app controls, independent of the wall clock:

#include <windows.h>
#include <iostream>

// GetTickCount64() is monotonic (counts since boot) and unaffected by clock changes
bool isSuspiciousTimeChange(ULONGLONG lastKnownTick, ULONGLONG lastKnownWallTime,
                             ULONGLONG currentWallTime) {
    ULONGLONG currentTick = GetTickCount64();
    ULONGLONG elapsedTicks = (currentTick - lastKnownTick) / 1000; // seconds
    ULONGLONG elapsedWall  = currentWallTime - lastKnownWallTime;   // seconds

    // If wall-clock elapsed time diverges significantly from monotonic elapsed time,
    // the user likely changed the system clock backward (or forward).
    long long drift = (long long)elapsedWall - (long long)elapsedTicks;
    return (drift < -60 || drift > 60); // allow small NTP drift tolerance
}

Store lastKnownTick/lastKnownWallTime encrypted, on each app run, and compare. This defeats the most common trial-reset trick (rolling the clock back) without needing OS-level lockdown at all, and it’s the approach most commercial software actually uses.

4. Group Policy / registry lockdown (enterprise/kiosk scenarios)

If this is for a managed fleet of machines rather than a general consumer app, Group Policy is the right tool, not app code: Computer Configuration → Windows Settings → Security Settings → Local Policies → User Rights Assignment, or lock the Date & Time control panel via NoSetTime / NoSetTimeZone registry policies under HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer (values 1 disable those UI panels — but note this only hides the UI, not the underlying API, so pair it with the privilege removal in #1 if you need real enforcement).

A note on the general approach

Full prevention against a local admin is essentially impossible — anyone with admin rights on their own machine can eventually work around client-side restrictions. The realistic, standard design for this problem (used by real commercial software) is: restrict casually via policy where you can (#1, #4), and detect/react robustly where you can’t (#2, #3) — treat client-side checks as a speed bump against casual users, not a cryptographic guarantee, and do the things that actually matter (license validity, entitlements) server-side if the stakes are high.

Good question — but there’s an important concept here first: a Unix timestamp (10-digit seconds / 13-digit milliseconds) is always the same number everywhere in the world, regardless of timezone. It represents an absolute instant (seconds/milliseconds since Jan 1, 1970 UTC), not a local wall-clock time. Tokyo and New York have different local times right now, but they’d compute the exact same timestamp number for “this instant.”

So there are really two different things you might actually want:

  1. “What’s the current timestamp?” → same number regardless of timezone (below, section A).
  2. “I have a specific local date/time in Tokyo (or NY) — convert that to a timestamp.” → this is where timezone actually matters, because you’re interpreting a wall-clock time as belonging to a specific zone (section B).

A. Current 10-digit and 13-digit timestamps (timezone-independent)

C++

#include <iostream>
#include <chrono>

int main() {
    using namespace std::chrono;

    auto now = system_clock::now();

    // 10-digit: seconds since epoch
    long long seconds = duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();

    // 13-digit: milliseconds since epoch
    long long milliseconds = duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();

    std::cout << "10-digit (seconds):      " << seconds << "\n";
    std::cout << "13-digit (milliseconds): " << milliseconds << "\n";

    return 0;
}

Output:

10-digit (seconds):      1788234852
13-digit (milliseconds): 1788234852123

C

#include <stdio.h>
#include <time.h>

int main(void) {
    // 10-digit seconds
    time_t seconds = time(NULL);
    printf("10-digit (seconds): %lld\n", (long long)seconds);

    // 13-digit milliseconds (POSIX clock_gettime)
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    long long milliseconds = (long long)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
    printf("13-digit (milliseconds): %lld\n", milliseconds);

    return 0;
}

Run this on a machine set to Tokyo time and one set to New York time simultaneously — you’ll get the identical number both places. That’s the whole point of Unix time: it’s timezone-agnostic by design.

B. Convert a specific local date/time in a timezone → timestamp

This is likely what you actually want if you’re thinking “the Tokyo timestamp.” Example: “What’s the timestamp for 2026-09-01 14:30:00 local time in Tokyo?”

C++20 (<chrono> with timezone database)

#include <iostream>
#include <chrono>

int main() {
    using namespace std::chrono;

    // Define a local wall-clock date/time
    auto localTime = local_days{2026y/9/1} + 14h + 30min;

    // Interpret it as belonging to Tokyo's timezone
    auto tokyoZoned = zoned_time{"Asia/Tokyo", localTime};
    auto tp = tokyoZoned.get_sys_time(); // convert to absolute UTC time_point

    long long seconds10 = duration_cast<std::chrono::seconds>(tp.time_since_epoch()).count();
    long long ms13 = duration_cast<milliseconds>(tp.time_since_epoch()).count();

    std::cout << "Tokyo 2026-09-01 14:30 local\n";
    std::cout << "10-digit: " << seconds10 << "\n";
    std::cout << "13-digit: " << ms13 << "\n";

    // Same wall-clock time, but interpreted as New York local time instead
    auto nyZoned = zoned_time{"America/New_York", localTime};
    auto tpNY = nyZoned.get_sys_time();
    std::cout << "\nSame clock reading, but as New York local\n";
    std::cout << "10-digit: " << duration_cast<std::chrono::seconds>(tpNY.time_since_epoch()).count() << "\n";

    return 0;
}

Output (illustrative):

Tokyo 2026-09-01 14:30 local
10-digit: 1788240600
13-digit: 1788240600000

Same clock reading, but as New York local
10-digit: 1788269400

Notice the two 10-digit numbers are different — same wall-clock reading (14:30), but a different absolute instant depending on which timezone you say it belongs to. That’s the mechanism that actually matters.

Portable fallback (works on any compiler, C or C++) using TZ + mktime

#include <iostream>
#include <ctime>
#include <cstdlib>

long long localTimeToTimestamp(const char* tz, int year, int month, int day,
                                int hour, int min, int sec) {
#ifdef _WIN32
    _putenv_s("TZ", tz);
    _tzset();
#else
    setenv("TZ", tz, 1);
    tzset();
#endif
    struct tm t = {};
    t.tm_year = year - 1900;
    t.tm_mon  = month - 1;
    t.tm_mday = day;
    t.tm_hour = hour;
    t.tm_min  = min;
    t.tm_sec  = sec;
    t.tm_isdst = -1; // let mktime figure out DST

    time_t result = mktime(&t); // interprets t as local time in current TZ setting
    return (long long)result;
}

int main() {
    long long tokyoTs = localTimeToTimestamp("Asia/Tokyo", 2026, 9, 1, 14, 30, 0);
    long long nyTs    = localTimeToTimestamp("America/New_York", 2026, 9, 1, 14, 30, 0);

    std::cout << "Tokyo 14:30 ->    10-digit: " << tokyoTs << ", 13-digit: " << tokyoTs * 1000 << "\n";
    std::cout << "New York 14:30 -> 10-digit: " << nyTs    << ", 13-digit: " << nyTs * 1000 << "\n";

    return 0;
}

Summary

What you want Approach
Current instant, as a timestamp A — timezone doesn’t affect the number
A specific local date/time in Tokyo/NY, converted to a timestamp B — timezone determines the number
Display an existing timestamp as Tokyo/NY local time Use zoned_time{tz, time_point} and print it (from my earlier answer)

If what prompted this is something like “the server timestamps things in UTC but I need to compare against a user’s local Tokyo time” — that’s case B, and the right pattern is: always store/transmit timestamps as the raw epoch number (A), and only convert to/from local time at the display or input boundary. Let me know which direction you’re actually working with and I can narrow the example further.