Terraform Date and Time Functions
Time and date manipulation is essential when working with infrastructure configurations, especially for setting resource lifetimes, scheduling operations, or generating timestamps. Terraform provides several built-in functions that allow you to work with dates and times efficiently within your configurations.
Introduction to Date and Time Functions
Terraform's date and time functions help you manage timestamps, calculate time differences, and format dates according to your needs. These functions are particularly useful when:
- Setting expiration dates for resources
- Adding timestamps to resource names
- Calculating time periods for scheduled operations
- Formatting dates for logging or output purposes
Let's explore the various date and time functions available in Terraform and how to use them effectively.
Core Date and Time Functions
timestamp()
Function
The timestamp()
function returns the current UTC timestamp in RFC 3339 format.
locals {
current_time = timestamp()
}
output "current_timestamp" {
value = local.current_time
# Example output: 2025-03-25T14:30:45Z
}
This function is useful when you need to record when resources were created or updated.
formatdate()
Function
The formatdate()
function formats a timestamp into a string using a specified format.
locals {
current_time = timestamp()
formatted_date = formatdate("YYYY-MM-DD hh:mm:ss", local.current_time)
}
output "formatted_date" {
value = local.formatted_date
# Example output: 2025-03-25 14:30:45
}
The format string uses the following specifiers:
Specifier | Description | Example |
---|---|---|
YYYY | Four-digit year | 2025 |
YY | Two-digit year | 25 |
MM | Two-digit month | 03 |
M | Month without leading zero | 3 |
DD | Two-digit day of month | 25 |
D | Day of month without leading zero | 25 |
hh | Two-digit hour (24-hour clock) | 14 |
h | Hour without leading zero | 14 |
mm | Two-digit minute | 30 |
m | Minute without leading zero | 30 |
ss | Two-digit second | 45 |
s | Second without leading zero | 45 |
timeadd()
Function
The timeadd()
function adds a duration to a timestamp and returns a new timestamp.
locals {
current_time = timestamp()
one_hour_later = timeadd(local.current_time, "1h")
one_day_later = timeadd(local.current_time, "24h")
one_week_later = timeadd(local.current_time, "168h")
}
output "future_timestamps" {
value = {
current = local.current_time
one_hour_later = local.one_hour_later
one_day_later = local.one_day_later
one_week_later = local.one_week_later
}
}
Duration format accepts:
h
for hoursm
for minutess
for seconds
You can combine these units, such as 1h30m
for one hour and thirty minutes.
Practical Examples
Example 1: Creating Resources with Expiration Tags
A common use case is to tag resources with creation and expiration dates for tracking purposes.
locals {
current_time = timestamp()
expiration_time = timeadd(local.current_time, "720h") # 30 days later
}
resource "aws_s3_bucket" "temporary_bucket" {
bucket = "temp-data-processing-${formatdate("YYYYMMDD", local.current_time)}"
tags = {
Name = "Temporary Data Processing Bucket"
CreatedOn = formatdate("YYYY-MM-DD", local.current_time)
ExpiresOn = formatdate("YYYY-MM-DD", local.expiration_time)
ManagedBy = "Terraform"
}
lifecycle {
prevent_destroy = false
}
}
output "bucket_info" {
value = {
bucket_name = aws_s3_bucket.temporary_bucket.bucket
created_on = formatdate("YYYY-MM-DD", local.current_time)
expires_on = formatdate("YYYY-MM-DD", local.expiration_time)
}
}
Example 2: Setting Time-Based Conditions
You can use date and time functions in combination with Terraform's conditional expressions to implement time-based logic.
locals {
current_time = timestamp()
business_hours_start = formatdate("hh:mm", local.current_time) >= "08:00"
business_hours_end = formatdate("hh:mm", local.current_time) <= "17:00"
is_business_hours = local.business_hours_start && local.business_hours_end
# Set different instance sizes based on time
instance_type = local.is_business_hours ? "t3.medium" : "t3.small"
}
resource "aws_instance" "app_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = local.instance_type
tags = {
Name = "AppServer-${formatdate("YYYYMMDD-hhmmss", local.current_time)}"
DeployedDuring = local.is_business_hours ? "BusinessHours" : "NonBusinessHours"
}
}
Example 3: Creating Rotating Backup Schedule
This example demonstrates how to create a backup policy with rotating schedules using time functions.
locals {
current_time = timestamp()
day_of_week = formatdate("EEE", local.current_time)
day_of_month = formatdate("DD", local.current_time)
# Define backup types based on day
backup_type = {
"Mon" = "incremental"
"Tue" = "incremental"
"Wed" = "incremental"
"Thu" = "incremental"
"Fri" = "full"
"Sat" = "archive"
"Sun" = "verify"
}
# Special backup on first day of month
is_first_day = local.day_of_month == "01"
todays_backup = local.is_first_day ? "monthly-full" : local.backup_type[local.day_of_week]
}
resource "aws_backup_plan" "example" {
name = "backup-plan-${formatdate("YYYYMMDD", local.current_time)}"
rule {
rule_name = "daily-${local.todays_backup}-backup"
target_vault_name = "backup-vault"
schedule = "cron(0 12 * * ? *)"
lifecycle {
delete_after = local.todays_backup == "monthly-full" ? 365 : 30
}
}
tags = {
BackupType = local.todays_backup
CreatedOn = formatdate("YYYY-MM-DD", local.current_time)
}
}
output "backup_info" {
value = {
plan_name = aws_backup_plan.example.name
backup_type = local.todays_backup
created_on = formatdate("YYYY-MM-DD", local.current_time)
}
}
Advanced Usage with Time Calculations
Working with Time Zones
While Terraform's timestamp function returns UTC time, you can use the formatdate()
function with format specifiers that include time zone information:
locals {
current_utc = timestamp()
# Format with UTC time explicitly shown
utc_formatted = formatdate("YYYY-MM-DD'T'hh:mm:ss'Z'", local.current_utc)
# Add hours for different time zones (manual approach)
est_time = timeadd(local.current_utc, "-5h") # Eastern Standard Time (UTC-5)
pst_time = timeadd(local.current_utc, "-8h") # Pacific Standard Time (UTC-8)
cet_time = timeadd(local.current_utc, "1h") # Central European Time (UTC+1)
}
output "times_in_different_zones" {
value = {
utc_time = local.utc_formatted
est_time = formatdate("YYYY-MM-DD hh:mm:ss", local.est_time)
pst_time = formatdate("YYYY-MM-DD hh:mm:ss", local.pst_time)
cet_time = formatdate("YYYY-MM-DD hh:mm:ss", local.cet_time)
}
}
Calculating Time Differences
Terraform doesn't have a direct function to calculate the difference between two timestamps, but you can work around this by using the timeadd()
function with a negative duration:
locals {
start_time = "2025-01-01T00:00:00Z"
end_time = "2025-01-02T12:30:45Z"
# Calculate hours between timestamps (approximate method)
# First convert to same format
formatted_start = formatdate("YYYY-MM-DD'T'hh:mm:ss'Z'", local.start_time)
formatted_end = formatdate("YYYY-MM-DD'T'hh:mm:ss'Z'", local.end_time)
# Then use a counter approach with a known increment
hours_diff = ceil((
parseint(formatdate("YYYYMMDDhhmmss", local.end_time), 10) -
parseint(formatdate("YYYYMMDDhhmmss", local.start_time), 10)
) / 10000) # Rough approximation, divide by 10000 to get to hours
}
output "time_difference" {
value = "${local.hours_diff} hours (approximate)"
}
This is a simplified approach and may not be accurate for all cases, especially when dealing with time zones or daylight saving time changes.
Understanding Terraform's Date Handling Limitations
Terraform has some limitations when it comes to date and time operations:
- There's no built-in function to parse arbitrary date formats into timestamps
- Direct subtraction of dates is not supported natively
- Complex calendar operations (like "last Friday of the month") require workarounds
- Time zone handling is manual rather than supported by native functions
For complex date calculations, consider using external tools or data sources that can provide pre-calculated values.
Best Practices for Working with Dates in Terraform
- Consistency: Always use UTC in your configurations to avoid time zone issues
- Documentation: Comment your time calculations clearly for future reference
- Avoid Drift: Be cautious when using
timestamp()
in resource attributes as it changes on every plan/apply - Testing: Validate your date logic with
terraform console
before applying changes - Variables: Use variables for time-sensitive configurations so they can be adjusted easily
Summary
Terraform's date and time functions provide flexible ways to handle timestamps in your infrastructure configurations. While not as comprehensive as dedicated date libraries in programming languages, they offer essential functionality for most infrastructure automation needs.
The key functions to remember are:
timestamp()
- Get the current UTC timeformatdate()
- Format a timestamp according to specific patternstimeadd()
- Add a duration to a timestamp
By combining these functions with Terraform's other capabilities, you can implement sophisticated time-based infrastructure patterns, resource rotation schedules, and expiration management systems.
Additional Resources
- Terraform Functions Documentation
- RFC 3339 Timestamp Format
- Working with Time in Infrastructure as Code (IaC) - HashiCorp Blog
Exercises
-
Create a Terraform configuration that provisions an AWS EC2 instance with tags indicating when it was created and when it should be reviewed (30 days later).
-
Implement a naming convention for resources that includes the current date in the format
YYYY-MM-DD-resource-name
. -
Write a module that takes a timestamp input variable and outputs various formatted versions of that timestamp for different purposes (logging, display, file naming).
-
Create a configuration that uses the day of the week to determine resource settings (e.g., higher capacity on weekdays, lower on weekends).
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)