# Blog Post Date Management Guide

**Last Updated:** 2026-02-15

Complete guide for managing "last updated" dates for blog posts, including when to update dates, how dates are used in meta tags and schema.org, and maintenance procedures.

## Overview

Blog posts have two important dates:

- **`publication_date`**: The original publication date (never changes)
- **`modified_date`**: The last significant content update date (updates when content changes)

Both dates are stored in ISO 8601 format (`YYYY-MM-DDTHH:MM:SS+00:00`) in the blog post JSON files.

## Date Usage

### Meta Tags

The `modified_date` is used in the `article:modified_time` meta tag:

```html
<meta property="article:modified_time" content="2026-01-10T18:01:59+00:00" />
```

### Schema.org Markup

The `modified_date` is used in schema.org `dateModified` fields for both `Article` and `WebPage` schemas:

```json
{
  "@type": "Article",
  "datePublished": "2023-09-01T10:40:44+00:00",
  "dateModified": "2026-01-10T18:01:59+00:00"
}
```

### UI Display

The "last updated" date is displayed conditionally:

- **PostHeader component**: Shows updated date if it's 7+ days after publication date
- **PostCard component**: Shows updated date if it's 7+ days after publication date (default variant only)

Format: "Zuletzt aktualisiert: 10. Januar 2026"

## When to Update `modified_date`

### ✅ Update When:

- Post content HTML is modified significantly
- Title is changed (not just capitalization)
- Excerpt is rewritten
- Meta description is updated
- Featured image is changed
- FAQs are added, removed, or modified (questions or answers)
- Content structure changes (new sections, major rewrites)

### ❌ Do NOT Update When:

- Related posts are added/removed
- Internal links are updated
- Topics/clusters are reassigned
- Reading time is recalculated
- Minor formatting changes (spacing, punctuation)
- Metadata-only changes (author, category)

## Date Format Standards

### Required Format

- **ISO 8601**: `YYYY-MM-DDTHH:MM:SS+00:00` (preferred)
- **Timezone**: Always UTC (`+00:00` or `Z`)
- **No microseconds**: Remove `.123456` if present
- **String type**: Store as string in JSON, not number

### Parsing

The `parse_iso8601_date()` helper in `blog-template-helpers.php` supports both `Z` and `+00:00` timezone formats. New posts should use `+00:00` for consistency; existing posts with `Z` are parsed correctly.

### Examples

✅ **Correct:**

```json
{
  "publication_date": "2023-09-01T10:40:44+00:00",
  "modified_date": "2026-01-10T18:01:59+00:00"
}
```

❌ **Incorrect:**

```json
{
  "modified_date": "2026-01-10T18:01:59.391340" // Has microseconds
}
```

## Maintenance Scripts

### Audit Dates

Check all blog post dates for issues:

```bash
php v2/scripts/blog/audit-post-dates.php [--verbose] [--fix]
```

**What it checks:**

- Missing `modified_date` fields
- Invalid date formats
- Dates where `modified_date` < `publication_date`
- Date mismatches with file modification time

### Fix Date Formats

Normalize date formats across all posts:

```bash
php v2/scripts/blog/fix-post-dates.php [--dry-run] [--verbose]
```

**What it fixes:**

- Removes microseconds from dates
- Ensures UTC timezone
- Sets missing `modified_date` to file modification time
- Ensures `modified_date` >= `publication_date`

### Sync Dates from File Modification Time

Update `modified_date` based on file modification time:

```bash
php v2/scripts/blog/sync-dates-from-filemtime.php [--dry-run] [--force] [--verbose]
```

**⚠️ WARNING:** This script updates dates based on file modification time, which includes ANY file change (content, metadata, formatting). It is **NOT** called automatically by git hooks.

**When to use manually:**

- Initial date setup
- Manual bulk operations
- Recovery scenarios
- When you need to sync dates regardless of content changes

**When NOT to use:**

- Regular commits (git hook handles this automatically)
- When you only want dates updated for content changes

### Validate Dates

Validate all dates meet requirements:

```bash
php v2/scripts/blog/validate-post-dates.php [--verbose]
```

**What it validates:**

- All posts have `modified_date` set
- All dates are valid ISO 8601 format
- `modified_date` >= `publication_date`

### Detect Content Changes

Detect when content has changed and needs date update:

```bash
php v2/scripts/blog/detect-content-changes.php [--update] [--verbose]
```

**What it does:**

- Compares content hash with stored hash
- Identifies posts with significant content changes
- Optionally updates `modified_date` for changed posts

### Test Implementation

Test that dates are correctly implemented:

```bash
php v2/scripts/blog/test-date-implementation.php [--post=slug] [--category=category]
```

**What it tests:**

- JSON files have valid `modified_date`
- Meta tags use correct dates
- Schema.org uses correct dates
- Helper functions work correctly

## Workflow

### Regular Maintenance

**Weekly:**

```bash
# Validate all dates
php v2/scripts/blog/validate-post-dates.php

# Detect content changes
php v2/scripts/blog/detect-content-changes.php --update
```

**Monthly:**

```bash
# Full audit
php v2/scripts/blog/audit-post-dates.php --verbose

# Sync dates if needed
php v2/scripts/blog/sync-dates-from-filemtime.php --dry-run
```

### After Content Updates

**Automated (Recommended):**

When you commit blog post changes, the git pre-commit hook automatically:

1. Detects **actual content changes** (title, HTML, excerpt, meta, featured image) in staged blog files
2. Updates `modified_date` and `_content_hash` **only when content changes**
3. Stages updated JSON files if dates changed

**Important:** Dates update **only for content changes**, NOT for:

- Metadata changes (related_posts, topics, category)
- Formatting changes (JSON whitespace, indentation)
- Field additions (new metadata fields)

**No manual steps required** - dates update automatically when you commit content changes!

**Manual (If needed):**

If you need to update dates manually:

1. **Make content changes** to JSON file
2. **Run detection script:**
   ```bash
   php v2/scripts/blog/detect-content-changes.php --update
   ```
3. **Verify dates:**
   ```bash
   php v2/scripts/blog/test-date-implementation.php --post=your-slug
   ```

### After Bulk Operations

After bulk content migrations or updates:

1. **Fix date formats:**
   ```bash
   php v2/scripts/blog/fix-post-dates.php
   ```
2. **Sync with file modification times:**
   ```bash
   php v2/scripts/blog/sync-dates-from-filemtime.php --force
   ```
3. **Validate everything:**
   ```bash
   php v2/scripts/blog/validate-post-dates.php
   php v2/scripts/blog/test-date-implementation.php
   ```

## Git Hook Automation

### Overview

The git pre-commit hook automatically detects **content changes** for staged blog post JSON files and updates dates accordingly. This ensures dates only reflect actual content changes, not metadata or formatting updates.

### How It Works

When you stage and commit blog post JSON files:

1. **Content Change Detection** (`scripts/blog/pre-commit-detect-changes.sh`):

   - Detects staged blog JSON files
   - Compares content hash (title, HTML, excerpt, meta, featured image) with stored hash
   - Updates `modified_date` and `_content_hash` **only if content changed**
   - Stages updated files if dates/hashes changed

2. **Documentation Checks** (existing):
   - Validates documentation files
   - Continues with normal commit process

**What Triggers Date Updates:**

- ✅ Title changes
- ✅ Content HTML changes
- ✅ Excerpt changes
- ✅ Meta description changes
- ✅ Featured image changes

**What Does NOT Trigger Date Updates:**

- ❌ Related posts changes
- ❌ Topics changes
- ❌ Category changes
- ❌ Formatting changes (JSON whitespace)
- ❌ Field additions (new metadata fields)

### Hook Location

- **Main hook**: `.git/hooks/pre-commit`
- **Blog detect script**: `scripts/blog/pre-commit-detect-changes.sh`
- **Manual sync script**: `scripts/blog/pre-commit-sync-dates.sh` (for manual use only)

### Bypassing Hooks

If you need to bypass the hook (not recommended):

```bash
git commit --no-verify -m "Your commit message"
```

**Warning**: Dates will not be automatically synced if you bypass the hook.

### Troubleshooting Git Hooks

**Hook not running:**

1. Check hook is executable:

   ```bash
   ls -l .git/hooks/pre-commit
   ```

   Should show `-rwxr-xr-x` (executable)

2. Make executable if needed:
   ```bash
   chmod +x .git/hooks/pre-commit
   chmod +x scripts/blog/pre-commit-detect-changes.sh
   ```

**Hook fails:**

1. Check error output in terminal
2. Review log files:
   - `/tmp/blog-detect-changes.log` - Content detection errors
3. Fix issues and retry commit

**Dates not updating:**

- Verify content actually changed (title, HTML, excerpt, meta, featured image)
- Metadata changes (related_posts, topics) do NOT trigger date updates
- Check log file to see if content hash changed

**Hook too slow:**

- Hook only runs on staged blog files
- If no blog files staged, hook exits immediately
- Script is optimized for performance

## Best Practices

### SEO Best Practices

1. **Always include `dateModified`** in schema.org markup
2. **Always include `article:modified_time`** in meta tags
3. **Ensure `dateModified` >= `datePublished`**
4. **Update dates when content is significantly revised**
5. **Don't update dates for minor changes** (maintains trust)

### Content Editor Guidelines

1. **When editing content**: Dates update automatically via git hook (no action needed)
2. **When making minor fixes**: Don't manually update dates - git hook handles it
3. **When making major updates**: Git hook automatically detects and updates dates
4. **Check dates before publishing**: Dates are validated automatically on commit

### Developer Guidelines

1. **Git hook handles date sync** - no manual steps needed
2. **Dates update automatically** when committing blog post changes
3. **Validate dates** if hook fails or you bypass it
4. **Document date changes** in commit messages (hook updates are automatic)

## Troubleshooting

### Dates Not Showing in UI

**Issue**: Updated date not visible on post page

**Check:**

- Is `modified_date` 7+ days after `publication_date`?
- Is `modified_date` set correctly in JSON?
- Are helper functions loaded?

**Fix:**

```bash
php v2/scripts/blog/test-date-implementation.php --post=your-slug
```

### Invalid Date Format Errors

**Issue**: Date format validation errors

**Fix:**

```bash
php v2/scripts/blog/fix-post-dates.php
```

### Dates Out of Sync

**Issue**: Dates don't match file modification times

**Fix:**

```bash
php v2/scripts/blog/sync-dates-from-filemtime.php --force
```

### Schema Validation Errors

**Issue**: Google Rich Results Test shows date errors

**Check:**

- Dates are valid ISO 8601 format
- `dateModified` >= `datePublished`
- Dates are in UTC timezone

**Fix:**

```bash
php v2/scripts/blog/fix-post-dates.php
php v2/scripts/blog/validate-post-dates.php
```

## Testing

See [Git Hook Testing Guide](GIT_HOOK_TESTING.md) for detailed testing procedures and scenarios.

## Related Documentation

- [Git Hook Testing Guide](GIT_HOOK_TESTING.md) - Testing procedures for git hooks
- [Blog Template Development Guide](TEMPLATE_DEVELOPMENT_GUIDE.md) - Template structure and components
- [Blog Data Structure Mapping](DATA_STRUCTURE_MAPPING.md) - JSON schema definitions
- [Blog Template Best Practices](BLOG_TEMPLATE_BEST_PRACTICES.md) - Best practices guide

## Script Reference

All scripts are located in `v2/scripts/blog/`:

- `audit-post-dates.php` - Audit all dates
- `fix-post-dates.php` - Fix date formats
- `sync-dates-from-filemtime.php` - Sync dates from file mtime
- `validate-post-dates.php` - Validate dates
- `detect-content-changes.php` - Detect content changes
- `test-date-implementation.php` - Test implementation
