Working with Dates and Times#

GFQL predicates support filtering by datetime, date, and time values. This guide covers common patterns and gotchas when working with temporal data.

Required Imports#

# Core imports
import graphistry
from graphistry import n, e_forward, e_reverse, e_undirected

# Temporal predicates
from graphistry.compute import (
    gt, lt, ge, le, eq, ne, between, is_in,
    DateTimeValue, DateValue, TimeValue
)

# Standard datetime types
import pandas as pd
from datetime import datetime, date, time, timedelta
import pytz  # For timezone support

Supported Types and Standards#

Supported Python Types#

  • pd.Timestamp - Pandas timestamp

  • datetime - Python datetime

  • date - Date only (no time)

  • time - Time only (no date)

  • Wire protocol dicts - For ISO strings and JSON compatibility

# Use datetime objects
gt(pd.Timestamp("2023-01-01 12:00:00"))
between(datetime(2023, 1, 1), datetime(2023, 12, 31))

# Wire protocol dicts accept ISO strings
gt({"type": "datetime", "value": "2023-01-01T00:00:00", "timezone": "UTC"})

# Raw strings raise ValueError
gt("2023-01-01")  # ValueError

Creating from Strings#

# Timestamps
pd.Timestamp("2023-01-01T12:00:00Z")  # UTC
pd.Timestamp("2023-01-01 12:00:00")   # Naive

# Date/Time objects
date.fromisoformat("2023-01-01")      # date(2023, 1, 1)
time.fromisoformat("14:30:00")        # time(14, 30, 0)

Standards#

Wire Protocol Types#

For JSON serialization and cross-system compatibility:

  • DateTimeWire: {"type": "datetime", "value": "ISO-8601-string", "timezone": "IANA-timezone"}

  • DateWire: {"type": "date", "value": "YYYY-MM-DD"}

  • TimeWire: {"type": "time", "value": "HH:MM:SS[.ffffff]"}

Note: The timezone field is optional for DateTimeWire and defaults to “UTC” if omitted.

Basic Usage#

Datetime Filtering#

Filter nodes or edges based on datetime values:

import pandas as pd
from datetime import datetime
from graphistry import n
from graphistry.compute import gt, lt, between

# Filter nodes created after a specific datetime
recent_nodes = g.chain([
    n(filter_dict={"created_at": gt(pd.Timestamp("2023-01-01 12:00:00"))})
])

# Filter edges within a date range
date_range_edges = g.chain([
    n(edge_match={"timestamp": between(
        datetime(2023, 1, 1),
        datetime(2023, 12, 31)
    )})
])

Date-Only Filtering#

For date comparisons (ignoring time):

from datetime import date
from graphistry.compute import eq, ge

# Filter nodes by exact date
specific_date = g.chain([
    n(filter_dict={"event_date": eq(date(2023, 6, 15))})
])

# Filter nodes on or after a date
after_date = g.chain([
    n(filter_dict={"start_date": ge(date(2023, 1, 1))})
])

Time-Only Filtering#

Filter based on time of day:

from datetime import time
from graphistry.compute import is_in, between

# Filter events at specific times
morning_events = g.chain([
    n(filter_dict={"event_time": is_in([
        time(9, 0, 0),
        time(9, 30, 0),
        time(10, 0, 0)
    ])})
])

# Filter events in time range
business_hours = g.chain([
    n(filter_dict={"timestamp": between(
        time(9, 0, 0),
        time(17, 0, 0)
    )})
])

Timezone Support#

import pytz

# Timezone-aware filtering
eastern = pytz.timezone('US/Eastern')
tz_aware_filter = g.chain([
    n(filter_dict={
        "timestamp": gt(pd.Timestamp("2023-01-01 12:00:00", tz=eastern))
    })
])

Comparisons automatically handle timezone conversions.

Advanced Usage#

Mixed Temporal and Non-Temporal Predicates#

Combine temporal predicates with other filters:

from graphistry.compute import gt, lt, eq

# Complex filter with multiple conditions
complex_filter = g.chain([
    n(filter_dict={
        "created_at": gt(datetime(2023, 1, 1)),
        "status": eq("active"),
        "priority": gt(5)
    })
])

Using Wire Protocol Dictionaries Directly#

You can pass wire protocol dictionaries directly to predicates, which is useful for programmatic predicate creation or when working with JSON configurations:

# Pass wire protocol dictionaries directly
filter_with_dict = g.chain([
    n(filter_dict={"timestamp": gt({
        "type": "datetime",
        "value": "2023-01-01T12:00:00",
        "timezone": "UTC"
    })})
])

# Works with all temporal predicates
date_range_filter = g.chain([
    n(filter_dict={"event_date": between(
        {"type": "date", "value": "2023-01-01"},
        {"type": "date", "value": "2023-12-31"}
    )})
])

# And with is_in for multiple values
time_filter = g.chain([
    n(filter_dict={"event_time": is_in([
        {"type": "time", "value": "09:00:00"},
        {"type": "time", "value": "12:00:00"},
        {"type": "time", "value": "17:00:00"}
    ])})
])

This is the same format used by the wire protocol, making it easy to:

  • Store predicate configurations in JSON files

  • Build predicates programmatically from external data sources

  • Share predicate definitions between Python and other systems

Temporal Predicates in Multi-Hop Queries#

Use temporal filters in complex graph traversals:

# Find all transactions after a date, then their related accounts
recent_transactions = g.chain([
    n(filter_dict={"type": eq("transaction"), 
                   "date": gt(date(2023, 6, 1))}),
    n(edge_match={"relationship": eq("involves")}),
    n(filter_dict={"type": eq("account")})
])

Temporal Value Classes#

PyGraphistry provides three temporal value classes for precise control:

DateTimeValue#

For full datetime with optional timezone:

from graphistry.compute import DateTimeValue, gt

# Create datetime value with timezone
dt_value = DateTimeValue("2023-01-01T12:00:00", "US/Eastern")

# Use in predicate
filter_dt = g.chain([
    n(filter_dict={"timestamp": gt(dt_value)})
])

DateValue#

For date-only comparisons:

from graphistry.compute import DateValue, between

# Create date values
start = DateValue("2023-01-01")
end = DateValue("2023-12-31")

# Use in between predicate
year_filter = g.chain([
    n(filter_dict={"event_date": between(start, end)})
])

TimeValue#

For time-of-day comparisons:

from graphistry.compute import TimeValue, is_in

# Create time values
morning = TimeValue("09:00:00")
noon = TimeValue("12:00:00")

# Filter by specific times
time_filter = g.chain([
    n(filter_dict={"daily_event": is_in([morning, noon])})
])

Best Practices#

  1. Use Explicit Types: Always use pd.Timestamp, datetime, date, or time objects instead of strings to avoid ambiguity.

  2. Timezone Awareness: When working with timestamps across timezones, always specify timezones explicitly.

  3. Performance: Temporal comparisons are optimized for pandas DataFrames. For large datasets, ensure your datetime columns are properly typed.

  4. JSON Serialization: When serializing queries, temporal values are automatically converted to tagged dictionaries that preserve type and timezone information.

Unsupported Features#

Duration/Interval Support#

Currently, PyGraphistry does not support duration or interval types (e.g., ISO 8601 durations like “P1D” or “PT2H”). For duration-based queries:

# Instead of duration literals, calculate explicit timestamps
from datetime import datetime, timedelta

# Find events within last 7 days
now = datetime.now()
week_ago = now - timedelta(days=7)
recent_events = g.chain([
    n(filter_dict={"timestamp": gt(pd.Timestamp(week_ago))})
])

# For recurring intervals, use multiple conditions
business_days = g.chain([
    n(filter_dict={
        "timestamp": between(
            pd.Timestamp("2023-01-01"),
            pd.Timestamp("2023-12-31")
        )
    })
])

Common Patterns#

Filter Recent Data#

from datetime import datetime, timedelta

# Get data from last 30 days
thirty_days_ago = datetime.now() - timedelta(days=30)
recent_data = g.chain([
    n(filter_dict={"timestamp": gt(pd.Timestamp(thirty_days_ago))})
])

Business Hours Filtering#

# Filter events during business hours
business_hours = g.chain([
    n(filter_dict={
        "timestamp": between(time(9, 0, 0), time(17, 0, 0))
    })
])

Quarterly Data Analysis#

# Q1 2023 data
q1_2023 = g.chain([
    n(filter_dict={
        "date": between(
            date(2023, 1, 1),
            date(2023, 3, 31)
        )
    })
])

Error Handling#

# Strings raise ValueError - always use datetime objects
gt("2023-01-01")                # ValueError: Raw string not allowed
gt(pd.Timestamp("2023-01-01"))  # Correct: Use pandas Timestamp

See Also#