Skip to content

Date and Time Functions

Date and time functions provide operations for formatting dates and calculating time differences.

Formats a timestamp according to a specification string.

formatdate(spec, timestamp)

Parameters:

  • spec - Format specification string
  • timestamp - RFC 3339 timestamp string

Returns: Formatted date string

Format Specifiers:

  • YYYY - 4-digit year
  • YY - 2-digit year
  • MM - 2-digit month (01-12)
  • MMM - Abbreviated month name
  • MMMM - Full month name
  • DD - 2-digit day (01-31)
  • HH - 2-digit hour (00-23)
  • hh - 2-digit hour (01-12)
  • mm - 2-digit minute (00-59)
  • ss - 2-digit second (00-59)
  • AA - AM/PM

Example:

formatdate("YYYY-MM-DD", "2024-01-15T10:30:00Z") # Returns: "2024-01-15"
formatdate("DD MMM YYYY", "2024-01-15T10:30:00Z") # Returns: "15 Jan 2024"
formatdate("hh:mm AA", "2024-01-15T14:30:00Z") # Returns: "02:30 PM"
formatdate("YYYY-MM-DD HH:mm:ss", "2024-01-15T10:30:45Z") # Returns: "2024-01-15 10:30:45"

Adds a duration to a timestamp.

timeadd(timestamp, duration)

Parameters:

  • timestamp - RFC 3339 timestamp string
  • duration - Duration string (e.g., “1h”, “30m”, “2h30m”)

Returns: New timestamp after adding duration

Duration Units:

  • h - hours
  • m - minutes
  • s - seconds

Example:

timeadd("2024-01-15T10:00:00Z", "1h") # Returns: "2024-01-15T11:00:00Z"
timeadd("2024-01-15T10:00:00Z", "30m") # Returns: "2024-01-15T10:30:00Z"
timeadd("2024-01-15T10:00:00Z", "2h30m") # Returns: "2024-01-15T12:30:00Z"
timeadd("2024-01-15T10:00:00Z", "-1h") # Returns: "2024-01-15T09:00:00Z"
variable "created_at" {
default = "2024-01-15T10:30:00Z"
}
locals {
# Create readable names with timestamps
backup_name = "backup-${formatdate("YYYY-MM-DD-HHmmss", var.created_at)}"
snapshot_id = "snap-${formatdate("YYYYMMDD", var.created_at)}"
# Daily rotation names
log_file = "app-${formatdate("YYYY-MM-DD", var.created_at)}.log"
}
resource "container" "app" {
container_name = "app-${formatdate("YYYYMMDDHHmmss", var.created_at)}"
labels = {
created_at = var.created_at
expires_at = timeadd(var.created_at, "24h")
}
}
variable "maintenance_start" {
default = "2024-01-15T02:00:00Z"
}
locals {
# Calculate future times
maintenance_end = timeadd(var.maintenance_start, "30m")
# Next day at same time
next_maintenance = timeadd(var.maintenance_start, "24h")
}
resource "template" "schedule" {
source = <<-EOF
Maintenance Window:
Start: ${formatdate("YYYY-MM-DD hh:mm AA", var.maintenance_start)}
End: ${formatdate("YYYY-MM-DD hh:mm AA", local.maintenance_end)}
Duration: 30 minutes
Next: ${formatdate("YYYY-MM-DD hh:mm AA", local.next_maintenance)}
EOF
destination = "./maintenance-schedule.txt"
}
variable "log_timestamp" {
default = "2024-01-15T10:00:00Z"
}
locals {
# Generate time-based paths
log_dir = "./logs/${formatdate("YYYY/MM", var.log_timestamp)}"
log_file = "${local.log_dir}/app-${formatdate("DD", var.log_timestamp)}.log"
# Archive naming for previous month
archive_date = timeadd(var.log_timestamp, "-720h") # 30 days ago
archive_name = "logs-${formatdate("YYYY-MM", local.archive_date)}.tar.gz"
}
variable "retention_hours" {
default = 168 # 7 days
}
variable "created_at" {
default = "2024-01-15T10:00:00Z"
}
locals {
# Calculate expiration
expires_at = timeadd(var.created_at, "${var.retention_hours}h")
# Human-readable expiration
expiry_date = formatdate("MMMM DD, YYYY", local.expires_at)
}
resource "template" "metadata" {
source = jsonencode({
created = var.created_at
expires = local.expires_at
expires_human = "This resource expires on ${local.expiry_date}"
retention_hours = var.retention_hours
})
destination = "./metadata.json"
}
variable "backup_time" {
default = "2024-01-15T03:00:00Z"
}
locals {
# Daily backup times
daily_backup = formatdate("YYYY-MM-DD", var.backup_time)
weekly_backup = formatdate("YYYY-'W'ww", var.backup_time)
monthly_backup = formatdate("YYYY-MM", var.backup_time)
# Calculate next backup times
next_daily = timeadd(var.backup_time, "24h")
next_weekly = timeadd(var.backup_time, "168h") # 7 days
}
resource "exec" "backup" {
command = "backup.sh"
arguments = [
"--daily", local.daily_backup,
"--weekly", local.weekly_backup,
"--monthly", local.monthly_backup
]
environment = {
BACKUP_TIME = var.backup_time
BACKUP_ID = formatdate("YYYYMMDDHHmmss", var.backup_time)
NEXT_BACKUP = local.next_daily
}
}
variable "task_start" {
default = "2024-01-15T09:00:00Z"
}
variable "task_duration_minutes" {
default = 45
}
locals {
end_time = timeadd(var.task_start, "${var.task_duration_minutes}m")
# Create a schedule entry
schedule_entry = {
task = "lab-exercise"
start = formatdate("hh:mm AA", var.task_start)
end = formatdate("hh:mm AA", local.end_time)
duration = "${var.task_duration_minutes} minutes"
date = formatdate("YYYY-MM-DD", var.task_start)
}
}
resource "template" "schedule" {
source = jsonencode(local.schedule_entry)
destination = "./task-schedule.json"
}
variable "utc_time" {
default = "2024-01-15T14:30:00Z"
}
locals {
# Format for different contexts (all times are UTC)
iso_date = formatdate("YYYY-MM-DD", var.utc_time)
human_readable = formatdate("MMM DD, YYYY at hh:mm AA", var.utc_time)
filename_safe = formatdate("YYYY-MM-DD_HH-mm-ss", var.utc_time)
log_format = formatdate("YYYY-MM-DD HH:mm:ss", var.utc_time)
}
resource "template" "timestamps" {
source = <<-EOF
Event Timestamps (UTC):
ISO Format: ${local.iso_date}
Human Readable: ${local.human_readable}
Filename Safe: ${local.filename_safe}
Log Format: ${local.log_format}
EOF
destination = "./timestamps.txt"
}
  1. Use Consistent Formats: Standardize date formats across your lab

    locals {
    # Define standard formats
    date_format = "YYYY-MM-DD"
    time_format = "HH:mm:ss"
    datetime_format = "${local.date_format} ${local.time_format}"
    }
  2. Always Use UTC: All timestamps should be in UTC (RFC 3339 format)

    locals {
    # Document timezone assumptions
    event_time = "2024-01-15T10:30:00Z" # UTC
    # Note: All times are in UTC
    }
  3. Validate Time Inputs: Ensure timestamps are properly formatted

    variable "start_date" {
    type = string
    validation {
    condition = can(formatdate("YYYY", var.start_date))
    error_message = "start_date must be a valid RFC 3339 timestamp"
    }
    }
  4. Use Meaningful Names: Make time-based resources clear

    locals {
    # Clear naming for time-based resources
    daily_report = "report-${formatdate("YYYY-MM-DD", var.report_time)}"
    hourly_backup = "backup-${formatdate("YYYY-MM-DD-HH", var.backup_time)}"
    }