timestamp / formatdate / timeadd — 日時関数

1. 概要

  • timestamp — 現在のUTCタイムスタンプを取得する
  • formatdate — タイムスタンプを指定フォーマットで整形する
  • timeadd — タイムスタンプに期間を加算・減算する
  • 日時関数の実用パターンと注意点

Terraformの日時関数は、リソースに有効期限を設定したり、ログやタグにタイムスタンプを埋め込んだりする際に使います。ただし、timestamp()はapplyのたびに変わるため、適切な使い方を理解することが重要です。


2. timestamp — 現在時刻を取得する

timestamp()は現在のUTC時刻をRFC 3339形式(YYYY-MM-DDTHH:MM:SSZ)の文字列で返します。

# terraform consoleで確認
> timestamp()
"2026-06-06T12:34:56Z"

重要: timestamp()はTerraformの実行(plan/apply)のたびに異なる値を返します。そのため、resourceブロック内で直接使うと、applyのたびにリソースが「変更あり」と判定されます。


3. formatdate — タイムスタンプを整形する

formatdate(format, timestamp)は、RFC 3339のタイムスタンプを指定フォーマットの文字列に変換します。

# terraform consoleで確認
> formatdate("YYYY-MM-DD", "2026-06-06T12:34:56Z")
"2026-06-06"

> formatdate("YYYY/MM/DD hh:mm", "2026-06-06T12:34:56Z")
"2026/06/06 12:34"

> formatdate("DD MMM YYYY", "2026-06-06T12:34:56Z")
"06 Jun 2026"

主なフォーマット指定子

指定子意味
YYYY4桁年2026
MM2桁月06
DD2桁日06
hh2桁時(24時間)12
mm2桁分34
ss2桁秒56
MMM月の略称Jun

4. timeadd — 期間を加算・減算する

timeadd(timestamp, duration)は、タイムスタンプに期間("24h""30m""-7d"など)を加算した新しいタイムスタンプを返します。

# terraform consoleで確認
> timeadd("2026-06-06T00:00:00Z", "24h")
"2026-06-07T00:00:00Z"   # 1日後

> timeadd("2026-06-06T00:00:00Z", "8760h")
"2027-06-06T00:00:00Z"   # 365日後(1年後)

> timeadd("2026-06-06T00:00:00Z", "-1h")
"2026-06-05T23:00:00Z"   # 1時間前

5. ACM証明書の有効期限管理

timestamp()timeaddの組み合わせで証明書の有効期限を計算する例です。

terraform {
  required_version = ">= 1.9"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

variable "environment" {
  description = "環境名"
  type        = string
  default     = "dev"
}

locals {
  # apply時の日時を固定するにはvariableで外から渡す方法が推奨
  # timestamp()はplanごとに変わるため、タグ程度の用途に留める
  deploy_date = formatdate("YYYY-MM-DD", timestamp())
}

resource "aws_s3_bucket" "app_data" {
  bucket = "${var.environment}-app-data"

  tags = {
    Name        = "${var.environment}-app-data"
    Environment = var.environment
    ManagedBy   = "terraform"
    DeployDate  = local.deploy_date  # タグへの利用は許容範囲
  }
}

6. timestamp()のdrift問題と回避策

# ❌ 問題のあるパターン: applyのたびにIAMポリシーが再作成される
resource "aws_iam_policy" "temp_access" {
  name   = "temp-access"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect   = "Allow"
      Action   = ["s3:GetObject"]
      Resource = "*"
      Condition = {
        DateLessThan = {
          "aws:CurrentTime" = timeadd(timestamp(), "720h")  # planのたびに変わる
        }
      }
    }]
  })
}

# ✅ 解決策: variableで外から日時を渡す
variable "policy_expiry_time" {
  description = "ポリシーの有効期限(RFC 3339形式)"
  type        = string
  default     = "2026-12-31T23:59:59Z"
}

resource "aws_iam_policy" "temp_access_fixed" {
  name   = "${var.environment}-temp-access"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect   = "Allow"
      Action   = ["s3:GetObject"]
      Resource = "*"
      Condition = {
        DateLessThan = {
          "aws:CurrentTime" = var.policy_expiry_time  # 固定値
        }
      }
    }]
  })

  tags = {
    Name        = "${var.environment}-temp-access"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

7. 関連記事


8. まとめ

  • timestamp() — 現在のUTC時刻をRFC 3339形式で返す。planのたびに値が変わる点に注意
  • formatdate(format, ts) — タイムスタンプを任意のフォーマットに変換する
  • timeadd(ts, duration) — タイムスタンプに期間を加算・減算する
  • timestamp()をリソース属性に直接使うとdrift(常に変更ありと判定)が発生する
  • 固定の日時が必要な場合はvariableで外から渡すのが推奨

動作確認バージョン: Terraform >= 1.9 公式ドキュメント: https://developer.hashicorp.com/terraform/language/functions/timestamp