timecmp / plantimestamp — 時刻比較関数

1. 概要

  • timecmp — 2つのタイムスタンプを比較する
  • plantimestamp — planのタイムスタンプを返す(Terraform 1.5+)
  • timestamp()との違いと使い分け

2. timecmp — タイムスタンプを比較する

timecmp(timestamp_a, timestamp_b)は2つのRFC 3339形式のタイムスタンプを比較します。a < bのとき-1a == bのとき0a > bのとき1を返します。

# terraform consoleで確認
> timecmp("2026-01-01T00:00:00Z", "2026-06-01T00:00:00Z")
-1  # a < b

> timecmp("2026-06-01T00:00:00Z", "2026-01-01T00:00:00Z")
1   # a > b

> timecmp("2026-06-01T00:00:00Z", "2026-06-01T00:00:00Z")
0   # a == b

有効期限が切れているかチェックする

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"
}

variable "policy_expiry_time" {
  description = "ポリシーの有効期限(RFC 3339形式)"
  type        = string
  default     = "2026-12-31T23:59:59Z"
}

locals {
  # 有効期限が現在時刻より過去かどうかをチェック
  # timecmp(policy_expiry, now) < 0 → 有効期限切れ
  is_expired = timecmp(var.policy_expiry_time, timestamp()) < 0
}

resource "terraform_data" "expiry_check" {
  lifecycle {
    precondition {
      condition     = !local.is_expired
      error_message = "ポリシーの有効期限(${var.policy_expiry_time})が切れています。"
    }
  }
}

data "aws_ami" "amazon_linux_2023" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  tags = {
    Name          = "${var.environment}-web"
    Environment   = var.environment
    ManagedBy     = "terraform"
    PolicyExpiry  = var.policy_expiry_time
  }
}

3. plantimestamp — planのタイムスタンプ(Terraform 1.5+)

plantimestamp()はTerraformがplanを実行した時刻を返します。timestamp()との違いは、plantimestamp()はplan中に固定されるためapply時に値が変わらない点です。

# terraform consoleで確認
> plantimestamp()
"2026-06-06T12:00:00Z"  # planの実行時刻(apply中も同じ値)
locals {
  # plantimestamp()はplan実行時刻で固定される(apply時に変わらない)
  plan_time = plantimestamp()

  # timestamp()はapplyのたびに変わる(driftの原因になる)
  # apply_time = timestamp()  # ← これは使わない
}

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

  tags = {
    Name           = "${var.environment}-app"
    Environment    = var.environment
    ManagedBy      = "terraform"
    LastPlanTime   = local.plan_time  # planのタイムスタンプで固定
  }
}

4. timestamp() vs plantimestamp() vs variable

方法plan時apply時用途
timestamp()実行時刻apply時刻(異なる)タグ程度の用途に限る
plantimestamp()plan時刻plan時刻(同じ)planとapplyで一致が必要な場合
variableで渡す固定値固定値有効期限など固定が必要な値

5. 関連記事


6. まとめ

  • timecmp(a, b) — タイムスタンプの比較。-1(a0(a==b)、1(a>b)を返す
  • timecmp(expiry, timestamp()) < 0で有効期限切れをチェックできる
  • plantimestamp()(1.5+)はplan実行時刻で固定。timestamp()のdrift問題を回避できる
  • 固定の日時が必要な場合はvariableで外から渡すのが最も安全

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