Aptiwise
Aptiwise
Aptiwise DocumentationForm Layout Feature - Implementation CompleteForm Layout Feature Implementation Guide
Getting Started
ApprovalML AI Workflow GenerationS3 Workflow Storage ImplementationTest Mode Design for Workflow EngineTimezone Implementation GuideWorkflow Instance Architecture
User Guide
Workflow Types & Patterns
Technical guide

Timezone Implementation Guide

Timezone Implementation Guide

Overview

This document explains the timezone-aware timestamp handling implementation in the FlowFrog approval system. The system automatically detects user timezones and displays timestamps in the user's local timezone while maintaining UTC storage on the server.

Architecture

Server-Side (Backend)

Database Storage:

  • All timestamps are stored as timestamp with time zone in PostgreSQL
  • Server uses UTC timezone for all operations
  • Python backend uses datetime.now(UTC) for timestamp creation

API Response:

  • Timestamps are returned in ISO 8601 format (e.g., 2024-01-15T10:30:00Z)
  • UTC timezone is preserved in API responses

Client-Side (Frontend)

Timezone Detection:

  • Automatically detects user's browser timezone using Intl.DateTimeFormat().resolvedOptions().timeZone
  • Falls back to UTC if detection fails
  • Timezone is detected once on application load

Display Formatting:

  • All timestamps are converted to user's local timezone for display
  • Multiple formatting options available for different use cases
  • Consistent timezone handling across all components

Implementation Details

Core Utilities (frontend/src/utils/timezone.js)

The timezone utilities provide several formatting functions:

formatDate(dateString, options)

Formats date only (e.g., "Jan 15, 2024")

formatDate('2024-01-15T10:30:00Z') // "Jan 15, 2024"

formatDateTime(dateString, options)

Formats date and time (e.g., "Jan 15, 2024, 10:30 AM")

formatDateTime('2024-01-15T10:30:00Z') // "Jan 15, 2024, 10:30 AM"

formatRelativeTime(dateString)

Shows relative time (e.g., "2 hours ago", "3 days ago")

formatRelativeTime('2024-01-15T10:30:00Z') // "2 hours ago"

formatSmartDate(dateString)

Smart formatting that shows relative time for recent dates and full date for older ones

formatSmartDate('2024-01-15T10:30:00Z') // "Today at 10:30 AM"
formatSmartDate('2024-01-10T10:30:00Z') // "5 days ago"

formatWithTimezone(dateString, showTimezone)

Formats with timezone indicator (e.g., "Jan 15, 2024, 10:30 AM (EST)")

formatWithTimezone('2024-01-15T10:30:00Z') // "Jan 15, 2024, 10:30 AM (EST)"

React Hooks (frontend/src/hooks/useTimezone.js)

useTimezone()

Provides timezone-aware formatting functions and current timezone info:

const { timezone, formatSmartDate, formatWithTimezone } = useTimezone();

useTimezoneInfo()

Provides detailed timezone information for display:

const { timezoneInfo } = useTimezoneInfo();
// Returns: { full: "America/New_York", abbreviation: "EST", display: "EST (America/New_York)" }

Components

TimezoneIndicator

Displays current user timezone in the UI:

<TimezoneIndicator showIcon={true} showFullName={false} />

Usage Examples

Basic Usage in Components

import { formatSmartDate, formatWithTimezone } from '../../utils/timezone';

// In your component
<div>Created: {formatSmartDate(approval.created_at)}</div>
<div>Approved: {formatWithTimezone(approval.approved_at)}</div>

Using React Hooks

import { useTimezone } from '../../hooks/useTimezone';

function MyComponent() {
  const { formatSmartDate, timezone } = useTimezone();
  
  return (
    <div>
      <p>Your timezone: {timezone}</p>
      <p>Created: {formatSmartDate(data.created_at)}</p>
    </div>
  );
}

Displaying Timezone Information

import { useTimezoneInfo } from '../../hooks/useTimezone';
import TimezoneIndicator from '../common/TimezoneIndicator';

function Header() {
  const { timezoneInfo } = useTimezoneInfo();
  
  return (
    <header>
      <TimezoneIndicator showFullName={true} />
      <span>Current timezone: {timezoneInfo.display}</span>
    </header>
  );
}

Updated Components

The following components have been updated to use timezone-aware formatting:

Dashboard Components

  • PendingApprovalsSection.jsx - Shows submission times in user timezone
  • MySubmissionsSection.jsx - Shows submission and completion times
  • Navigation.jsx - Includes timezone indicator in the header

Approval Components

  • ApprovalUI.jsx - Shows creation and action timestamps
  • ApprovalUI2.jsx - Shows submission and approval times
  • ApprovalUI3.jsx - Shows workflow timestamps
  • approvals/[id]/page.js - Shows detailed approval timestamps
  • approvals/page.js - Shows approval list timestamps

Benefits

For Users

  • Consistent Experience: All timestamps displayed in user's local timezone
  • Clear Understanding: No confusion about server vs local time
  • Automatic Detection: No manual timezone configuration required
  • Smart Formatting: Recent events show relative time, older events show full date

For Developers

  • Centralized Logic: All timezone handling in one place
  • Easy to Use: Simple import and function calls
  • Consistent API: Same functions work across all components
  • Fallback Handling: Graceful degradation if timezone detection fails

For System

  • Data Integrity: Server always stores UTC timestamps
  • Scalability: Works for users in any timezone
  • Maintainability: Single source of truth for timezone logic

Testing

Manual Testing

  1. Change your browser/system timezone
  2. Refresh the application
  3. Verify timestamps display in the new timezone
  4. Check that timezone indicator updates correctly

Automated Testing

// Test timezone detection
const timezone = getUserTimezone();
expect(timezone).toBeDefined();

// Test formatting functions
const formatted = formatSmartDate('2024-01-15T10:30:00Z');
expect(formatted).toContain('2024');

Troubleshooting

Common Issues

Timezone not detected:

  • Check browser support for Intl.DateTimeFormat
  • Verify system timezone is set correctly
  • Check for JavaScript errors in console

Timestamps showing wrong time:

  • Verify server is returning UTC timestamps
  • Check that timezone detection is working
  • Ensure formatting functions are being used correctly

Inconsistent display:

  • Make sure all components use the timezone utilities
  • Check for hardcoded new Date().toLocaleString() calls
  • Verify timezone indicator is showing correct timezone

Debug Mode

Enable debug logging by adding to browser console:

localStorage.setItem('timezone_debug', 'true');

This will log timezone detection and formatting operations.

Future Enhancements

Planned Features

  • User Preferences: Allow users to override detected timezone
  • Time Range Selection: Date/time pickers with timezone awareness
  • Export Options: Export data with timezone information
  • Notifications: Timezone-aware notification scheduling

Performance Optimizations

  • Caching: Cache timezone detection results
  • Lazy Loading: Load timezone utilities only when needed
  • Bundle Optimization: Tree-shake unused formatting functions

Migration Guide

For Existing Components

If you have components using old timestamp formatting:

Before:

<span>{new Date(data.created_at).toLocaleDateString()}</span>
<span>{new Date(data.approved_at).toLocaleString()}</span>

After:

import { formatSmartDate, formatWithTimezone } from '../../utils/timezone';

<span>{formatSmartDate(data.created_at)}</span>
<span>{formatWithTimezone(data.approved_at)}</span>

For New Components

Always use the timezone utilities for any timestamp display:

import { formatSmartDate } from '../../utils/timezone';

// For recent events (shows relative time)
<span>{formatSmartDate(timestamp)}</span>

// For detailed views (shows full date/time with timezone)
<span>{formatWithTimezone(timestamp)}</span>

// For date-only display
<span>{formatDate(timestamp)}</span>

Conclusion

The timezone implementation provides a robust, user-friendly solution for handling timestamps across different timezones. It ensures users always see times in their local timezone while maintaining data integrity on the server side.

For questions or issues, refer to the troubleshooting section or contact the development team.

Test Mode Design for Workflow Engine

Previous Page

Workflow Instance Architecture

Understanding request_data vs context in workflow instances

On this page

Timezone Implementation GuideOverviewArchitectureServer-Side (Backend)Client-Side (Frontend)Implementation DetailsCore Utilities (frontend/src/utils/timezone.js)formatDate(dateString, options)formatDateTime(dateString, options)formatRelativeTime(dateString)formatSmartDate(dateString)formatWithTimezone(dateString, showTimezone)React Hooks (frontend/src/hooks/useTimezone.js)useTimezone()useTimezoneInfo()ComponentsTimezoneIndicatorUsage ExamplesBasic Usage in ComponentsUsing React HooksDisplaying Timezone InformationUpdated ComponentsDashboard ComponentsApproval ComponentsBenefitsFor UsersFor DevelopersFor SystemTestingManual TestingAutomated TestingTroubleshootingCommon IssuesDebug ModeFuture EnhancementsPlanned FeaturesPerformance OptimizationsMigration GuideFor Existing ComponentsFor New ComponentsConclusion