Pine Script time and date handling, and firing a command once per bar
Pine Script gives you a bar's timestamp, its calendar breakdown, and a way to check whether that bar falls inside a specific session, none of which the other Pine Script guides here touch. This page covers all three, then the piece that matters most for automation: using barstate.isconfirmed so a time- or date-based condition fires an Autoview command exactly once per bar, not once per realtime tick.
time, time_close, and timenow
Three built-ins hold different timestamps, all in UNIX format:
timeholds the current bar's opening time.time_closeholds the same bar's closing time. It'snaon an open realtime bar of a tick or price-based chart, since that bar hasn't closed yet.timenowholds the timestamp of the script's own current execution. It only updates when the script actually runs, so it isn't a live clock ticking independently of the chart.
barAgeSeconds = timenow - time
The calendar built-ins
Pine Script also breaks the current bar's time down into calendar components, all int values expressed in the exchange's time zone: year, month, weekofyear, dayofmonth, dayofweek, hour, minute, and second. There's no single built-in named day, it's dayofmonth and dayofweek as two separate variables:
isNewMonth = month != month[1]
if isNewMonth
label.new(bar_index, high, "New month", color=color.blue, textcolor=color.white)month != month[1] compares this bar's month to the previous bar's month; the label appears the first bar where they differ. Build a readable date string the same way, concatenating each piece with str.tostring():
dateString = str.tostring(year) + "-" + str.tostring(month) + "-" + str.tostring(dayofmonth)
Detecting a session with time()
Checking the hour manually works for a fixed UTC session, but real trading sessions are timezone-specific and don't all start on the hour. time(timeframe, session, timezone) handles both: it returns the current bar's UNIX timestamp if that bar opens or closes inside the session string you give it, in the timezone you give it, or na if it doesn't.
inLondonOpen = not na(time(timeframe.period, "0800-0900", "Europe/London"))inLondonOpen is true on every bar between 08:00 and 09:00 London time, false otherwise, regardless of the exchange time zone the chart itself is set to. timeframe.period passes the chart's own current timeframe through, which is what you want in most cases; time() also accepts a fixed timeframe string like "5" if you need it to check a specific resolution instead.
Timezones: syminfo.timezone and the timezone parameter
time() and timestamp() both take a timezone parameter. Left out, it defaults to the symbol's own exchange time zone; supplied, it accepts either a UTC-offset string like "UTC-5" or an IANA string like "America/New_York". syminfo.timezone holds the current symbol's exchange time zone as an IANA string, in case you need to reference or display it rather than hardcode a session's own zone:
exchangeTz = syminfo.timezone
Firing an alert exactly once per bar
A script re-runs on every new tick of a realtime bar, not just once when the bar finally closes. Left ungated, a condition built from any of the above can turn true several times on the same bar before it's done forming, and alert()'s default freq (alert.freq_once_per_bar) only limits repeats within a bar, it doesn't wait for the bar to close. barstate.isconfirmed is true only on a bar's final execution, its close, which makes it the gate for "exactly once, and only once the bar is done":
//@version=5
indicator("Session Open Once", overlay=true)
inLondonOpen = not na(time(timeframe.period, "0800-0900", "Europe/London"))
justEnteredSession = inLondonOpen and not inLondonOpen[1]
if justEnteredSession and barstate.isconfirmed
alert("s=EUR_USD b=buy q=1000 t=market", alert.freq_once_per_bar_close)justEnteredSession catches the bar-to-bar transition into the session window; barstate.isconfirmed holds the alert until that specific bar is confirmed closed, so it fires once, not once per intrabar update while the transition bar is still forming. Pairing it with alert.freq_once_per_bar_close as the freq argument reinforces the same intent on alert()'s own side.
Test before you trust it
Add d=1 to the message before you rely on any of this. Autoview's dry-run gate is exchange-agnostic: every integration's trade path calls a shared withDebugReporter check, and when cmd.d is set, it logs what the command would have done and returns before any live order is sent. Let justEnteredSession trigger across a few real session opens, check the log to confirm it only fired once per session, then remove d=1 once it matches.
A note on what Autoview is. Autoview is an execution tool, not a trading or investment advisor. It places the orders your script and alerts tell it to; it doesn't generate signals or make any claim about results. Trading carries risk of loss, and you're responsible for the strategy you automate. See our disclosures.