Converting time values into human-readable strings is a common requirement in Pine Script. Whether you need to display the current time on the chart, format timestamps for logging, or create custom alert messages, mastering time-to-string conversion is essential. This article delves into the core functions and techniques for handling time as strings effectively in your Pine Script indicators and strategies.
Introduction to Time Conversion in Pine Script
Pine Script manages time primarily as numerical timestamps, representing milliseconds since the Unix epoch (January 1, 1970, 00:00:00 UTC). However, these raw numbers are not easily interpretable by humans or suitable for direct display in labels or alert texts.
Understanding the Importance of Time as Strings
Time, when represented as a string, becomes a versatile piece of data that can be:
- Displayed on the chart using functions like
label.neworplotchar. - Included in alert messages to provide context about when an event occurred.
- Used for debugging or logging information via
log.infoor plots. - Incorporated into dynamic text for plots or labels.
Why Convert Time to String in Pine Script?
The primary reason is presentation and usability. While Pine Script functions like time and timenow provide the current time as a numerical timestamp, they lack inherent formatting capabilities. Converting them to strings allows you to present time in standard formats like YYYY-MM-DD HH:MM:SS, MM/DD HH:MM, or any other custom layout required by your script’s output.
Built-in Functions for Time Representation
Pine Script provides several built-in variables and functions to access time data.
Overview of timenow, time, and timestamp Functions
time: Returns the timestamp of the current bar’s opening time in milliseconds UTC. This is the most commonly used time variable for bar-specific logic.timenow: Returns the timestamp of the current server time in milliseconds UTC. This value updates continuously, even within a single bar. Useful for displaying real-time clock or for logic that depends on the precise moment in time, not just the bar’s time.timestamp(year, month, day, hour, minute, second): Constructs a specific timestamp in milliseconds UTC from individual date and time components. Useful for defining fixed points in time.
All these functions return numeric timestamps (type int or uint), which are the starting point for string conversion.
Understanding Time Zones and UTC Offset
Pine Script primarily operates with UTC timestamps internally. However, charts are displayed in the time zone configured in your TradingView profile or chart settings. Functions like hour(), minute(), dayofmonth(), etc., when used with time, return values based on the chart’s time zone. When converting a UTC timestamp (like those from time or timenow) to a string, it’s crucial to understand how the conversion function handles time zones, especially if you need to display time in a zone different from UTC.
TradingView’s string formatting functions typically respect the chart’s time zone unless explicitly told otherwise or when dealing with timestamps that inherently carry zone information (which standard Pine time/timenow do not in a way that affects the conversion output’s zone).
Converting Time to String Using str.format()
The str.format() function is the workhorse for creating formatted strings in Pine Script, including time.
Basic Usage of str.format() with Time Values
The str.format() function uses format specifiers similar to C-style printf. For time, the primary specifier is %T. You pass the numeric timestamp (in milliseconds) as one of the arguments.
// Example 1: Basic time formatting
//@version=5
indicator("Basic Time String", overlay = false)
// Get the current bar's time
barTime = time
// Format the time into a simple string (YYYY-MM-DD HH:MM:SS)
// %T is the specifier for time/date, it expects a timestamp in milliseconds
formattedTime = str.format("Bar time: %T", barTime)
// Plot the formatted string (only on the last bar for clarity)
var string displayTime = na
if barstate.islast
displayTime := formattedTime
plotchar(displayTime, title="Formatted Time", char='', location=location.top, color=color.blue, size=size.normal)
// Note: The format applied by default with %T depends on the Pine Script version and context.
// It's best practice to use explicit format specifiers.
In the example above, using just %T provides a default date/time format. However, for precise control, you need to use sub-specifiers within %T.
Customizing Time Format Strings
The %T specifier supports various sub-specifiers preceded by a % sign within the format string. These sub-specifiers define how specific parts of the date and time should be represented.
Common Time Sub-specifiers:
%y: Year without century (00-99)%Y: Year with century (e.g., 2023)%m: Month as a decimal number (01-12)%d: Day of the month as a decimal number (01-31)%H: Hour (24-hour clock) as a decimal number (00-23)%M: Minute as a decimal number (00-59)%S: Second as a decimal number (00-59)%A: Weekday as a full name (e.g., Monday)%b: Abbreviated month name (e.g., Jan)%B: Full month name (e.g., January)%I: Hour (12-hour clock) as a decimal number (01-12)%p: AM or PM designation%Z: Time zone name (often empty or unreliable for standardtime/timenow)%z: UTC offset (+/-HHMM)
These can be combined to create custom date and time strings.
Examples: Formatting Time in Various Ways (e.g., HH:MM:SS, YYYY-MM-DD)
// Example 2: Custom time formatting
//@version=5
indicator("Custom Time Strings", overlay = false)
barTime = time // Current bar's time (UTC)
// Format 1: YYYY-MM-DD
formatDateOnly = str.format("%T{%Y-%m-%d}", barTime)
// Format 2: HH:MM:SS (using chart's time zone interpretation of barTime)
formatTimeOnly = str.format("%T{%H:%M:%S}", barTime)
// Format 3: YYYY/MM/DD HH:MM:SS
formatFull = str.format("%T{%Y/%m/%d %H:%M:%S}", barTime)
// Format 4: Month Day, Year Hour:Minute AM/PM
formatReadable = str.format("%T{%B %d, %Y %I:%M %p}", barTime)
// Format 5: Including UTC offset
formatWithOffset = str.format("%T{%Y-%m-%d %H:%M:%S %z}", barTime)
// Displaying these on the last bar
var string displayStrings = na
if barstate.islast
displayStrings := "Date: " + formatDateOnly + "\n" +
"Time: " + formatTimeOnly + "\n" +
"Full: " + formatFull + "\n" +
"Readable: " + formatReadable + "\n" +
"Offset: " + formatWithOffset
plotchar(displayStrings, title="Formatted Times", char='', location=location.top, color=color.navy, size=size.normal)
Notice the use of {%...} within the %T specifier. This block contains the specific layout string using the sub-specifiers. The output respects the time zone of the chart when interpreting the UTC timestamp from time.
Advanced Time String Formatting
While str.format covers most needs, certain scenarios require deeper consideration.
Dealing with Time Zones and Converting Them
The str.format function with %T interprets the timestamp based on the chart’s time zone. If you need to display time in a different time zone, Pine Script does not have a direct built-in function to convert a timestamp to a string formatted for an arbitrary time zone name (like ‘America/New_York’).
The typical approach if you needed a specific different zone would be to calculate the timestamp offset yourself and add/subtract it before formatting. However, this is complex due to daylight saving time. For most standard TradingView use cases, relying on the chart’s time zone interpretation of the timestamp is sufficient and recommended.
The %z specifier displays the UTC offset of the chart’s time zone at that specific time, not necessarily the offset of the input timestamp itself if it originated from a different zone context.
Displaying Session Times as Strings
Often, traders are interested in the start/end times of specific trading sessions (e.g., London open, NY close) in their local chart time. You can determine if the current bar falls within a session using time(timezone, session_spec). However, getting the string representation of the session’s start/end time isn’t a direct function call.
You would typically define the session times numerically (e.g., hour/minute) and then either construct the string manually or use timestamp() to create a timestamp for the session start/end on a specific date and then format that timestamp.
// Example: Manually building a session time string
//@version=5
indicator("Session Time String Example", overlay = false)
// Example session: 09:30 to 16:00 in chart timezone
string sessionSpec = "0930-1600"
// Check if current bar is within session (uses chart timezone)
bool inSession = time(timeframe.period, sessionSpec) != 0
// Get bar time components in chart timezone
int chartHour = hour(time)
int chartMinute = minute(time)
// Build a simple session time string for display (chart timezone)
string currentTimeStr = str.format("{0}:{1}",
str.format("{0,number,integer,pad=2}", chartHour),
str.format("{0,number,integer,pad=2}", chartMinute))
plotchar(inSession ? "In Session: " + currentTimeStr : "Outside Session: " + currentTimeStr,
title="Session Status", char='', location=location.top, color=inSession ? color.green : color.red, size=size.normal)
This example manually formats the current bar’s hour and minute (which hour() and minute() correctly return in the chart’s time zone) into a string. For the session start/end itself, you’d need to know the date and use timestamp() or build the strings based on known numerical values.
Using Conditional Logic in Time String Formatting
You can use conditional logic (e.g., if, ?:) to include different information or format the time string differently based on certain conditions, just like with any other Pine Script variable.
// Example: Conditional time string based on bar state
//@version=5
indicator("Conditional Time String", overlay = false)
barTime = time
serverTime = timenow
string timeToDisplay = barstate.islast
? str.format("Last Bar Time: %T{%H:%M:%S}", barTime) + "\n" +
str.format("Server Time: %T{%H:%M:%S}", serverTime)
: str.format("Bar Time: %T{%H:%M}", barTime)
plotchar(timeToDisplay, title="Time Info", char='', location=location.top, color=color.purple, size=size.small)
This shows how you can create a multi-line string with different content depending on whether it’s the last bar.
Practical Applications and Examples
Let’s look at how formatted time strings are used in practice.
Displaying Current Time on Chart
Using timenow and str.format is ideal for displaying the current server time on the chart, updating tick by tick.
// Example: Displaying Real-time Clock
//@version=5
indicator("Real-time Clock", overlay = true)
// Get current server time (updates continuously)
int currentTime = timenow
// Format the time string (e.g., HH:MM:SS)
// Using %Z or %z might show the broker server's timezone offset,
// but %T interprets the timestamp based on *your chart's* timezone for HH:MM:SS.
string timeString = str.format("%T{%H:%M:%S}", currentTime)
// Display the time string using a label on the last bar
var label timeLabel = na
if barstate.islast
// Delete previous label
if na(timeLabel) == false
label.delete(timeLabel)
// Create new label at current price, anchored to the right
timeLabel := label.new(bar_index, close, text=timeString,
xloc=xloc.bar_index, yloc=yloc.price, style=label.style_label_left,
color=color.blue, textcolor=color.white, size=size.normal)
// Update label text on new ticks (in real-time or small timeframes)
if not barstate.islast
// You can update text of existing label, but creating a new one on last bar is often simpler.
// label.set_text(timeLabel, timeString) // This requires timeLabel to persist across bars, which is tricky.
// The example above deletes and recreates, suitable for end-of-bar or last-bar display.
// For truly tick-by-tick updating on the chart, you might use plotchar with location.top/bottom or a more complex label management.
// A simpler approach for plotchar (updates per bar, but useful demonstration)
// plotchar(barstate.islast ? timeString : na, title="Clock", char='', location=location.top, color=color.blue)
This method uses label.new to place the formatted time on the last bar. Since timenow updates intra-bar, the label text could be updated if you manage label persistence, but the delete/recreate on barstate.islast is a common pattern for ensuring the label is only present and correct on the very last, current bar.
Creating Alerts Based on Time Conditions (String-based)
While most time-based alerts use direct numerical comparisons with hour(), minute(), etc., you can incorporate formatted time strings into the alert message itself.
// Example: Alert with formatted time in message
//@version=5
indicator("Time Alert Message", overlay = true)
// Alert condition: Trigger every hour exactly at minute 00 on the last bar
bool alertCondition = barstate.islast and minute(time) == 0 and minute(time[1]) != 0
// Get current bar time components in chart timezone
int h = hour(time)
int m = minute(time)
int s = second(time)
// Format time for the alert message
string alertTimeString = str.format("%02d:%02d:%02d", h, m, s)
// Define the alert message
string alertMsg = "Hourly trigger at " + alertTimeString + " on " + syminfo.ticker
// Trigger alert
if alertCondition
alert(alertMsg, alert.freq_once_per_bar)
Here, we use str.format before the alert call to build a descriptive message that includes the exact time (in the chart’s timezone) the alert condition was met.
Using Time Strings to Log Events
Logging events with timestamps is invaluable for debugging and understanding strategy execution. Pine Script’s logging functions log.info, log.warning, log.error accept strings and are perfect for this.
// Example: Logging with Timestamps
//@version=5
strategy("Log with Timestamp", overlay = true)
// Example entry condition (dummy)
bool longCondition = ta.crossover(ta.sma(close, 15), ta.sma(close, 30))
// Get current bar's time in chart timezone components
int y = year(time)
int m = month(time)
int d = dayofmonth(time)
int h = hour(time)
int min = minute(time)
// Format the time string for logging
string logTimestamp = str.format("[%04d-%02d-%02d %02d:%02d]", y, m, d, h, min)
// Log entry event with timestamp
if longCondition
strategy.entry("Long", strategy.long)
log.info(logTimestamp + " Entered Long position.")
// Log exit event (dummy)
bool exitCondition = ta.crossunder(ta.sma(close, 15), ta.sma(close, 30))
if exitCondition
strategy.close("Long")
log.info(logTimestamp + " Exited Long position.")
// You can view logs in the Strategy Tester -> Logs tab or Pine Script Editor -> Pine Logs tab.
This demonstrates formatting the bar’s date and time and prepending it to log messages, providing a clear chronological record of events during strategy backtesting or live trading.
Mastering time string conversion in Pine Script provides robust capabilities for enhancing the presentation, logging, and alerting features of your scripts. The str.format() function with its %T specifier and various sub-specifiers is the primary tool for this, allowing you to tailor time representations precisely to your needs.