Monitor your key's usage before you hit a limit
Watching your quota headers as you go tells you when a limit is approaching, well before a request actually gets rejected.
A timestamp displayed in your server's time zone reads correctly to almost nobody except whoever happens to sit in that same zone, which for a site with visitors anywhere is close to nobody at all.
An IP lookup returns a timezone field directly, giving you the identifier needed to localize any timestamp on the page.
GET /v1/ip?ip=203.0.113.77{
"status": "ok",
"ip": "203.0.113.77",
"version": 4,
"found": true,
"country": "Brazil",
"country_code": "BR",
"region": "Rio de Janeiro",
"city": "Rio de Janeiro",
"postcode": "20040",
"lat": -22.9068,
"lon": -43.1729,
"timezone": "America/Sao_Paulo",
"asn": 5566,
"org": "Example ISP"
}Store every timestamp in your database in UTC, as usual, and convert to the visitor's local zone only at display time, on the server, using the timezone identifier you looked up. Since this site renders everything server-side with no client-side JavaScript, the conversion and formatting both happen before the page is sent, not afterward in the browser.
local_time = convert_to_timezone(stored_utc_timestamp, "America/Sao_Paulo")An order confirmation page showing "placed at" and "expected by" times is a good example of where this matters beyond a simple page header clock. Converting both timestamps through the same visitor zone, rather than leaving one in server time by oversight, keeps the two figures consistent and avoids a confusing situation where the expected delivery time appears to be earlier than the order time because one was converted and the other was not.
Time zone and format are related but separate choices. A visitor in a zone that commonly uses a 24-hour clock and day-month-year date order benefits from formatting that matches, not just a shifted hour value written in a format that still looks foreign. Pair the country_code from the same IP lookup with a small formatting lookup table if you want to go beyond just adjusting the hour.
Do not implement the conversion as a fixed hour offset calculated once and applied to every timestamp going forward. A zone's actual offset from UTC can change over the course of the year with daylight saving, so a timestamp converted correctly in one season can come out an hour wrong in another if the code applies a stored offset number rather than converting through the timezone identifier itself using a proper date and time library.
Not every time zone sits at a whole-hour offset from UTC. Some are offset by 30 or 45 minutes rather than a full hour. Relying on a date library that understands the full IANA time zone identifier, rather than a simplified hour-only offset value, handles this correctly without any special-case code on your part. The utc_offset and abbreviation fields from the timezone lookup docs are useful if you want to display the offset explicitly alongside a converted time.
Look up the time zone once per visitor session and reuse it for every timestamp rendered on every page during that visit, rather than calling the API again for each individual date shown, since the zone itself does not change mid-session.
One lookup per new session covers localization for every timestamp shown during that visit, one request regardless of how many dates appear on the page. This keeps even a content-heavy site well within the 2,500 free requests a day included with every key.
Getting local time and date formatting right across a whole site comes down to one lookup per session and consistent server-side rendering after that. The IPv4 lookup docs and timezone lookup docs cover both approaches to getting the zone.