# How to Use Protobuf Well-Known Types: Any, Timestamp, and Duration

> Master Protobuf well-known types Any Timestamp and Duration Learn to wrap messages with Any track absolute UTC timestamps with Timestamp and manage time spans using Duration

- Repository: [Protocol Buffers/protobuf](https://github.com/protocolbuffers/protobuf)
- Tags: how-to-guide
- Published: 2026-03-02

---

**Use `google.protobuf.Any` to wrap arbitrary messages with type URLs, `google.protobuf.Timestamp` for absolute UTC timestamps, and `google.protobuf.Duration` for signed time spans.**

Protobuf well-known types provide standardized, cross-language message definitions for common data patterns. Defined in the `protocolbuffers/protobuf` repository, these types ensure consistent binary wire format and JSON mapping across all supported languages.

## Understanding Protobuf Well-Known Types

### What Are Well-Known Types?

Well-known types are a set of protocol buffer message definitions maintained by Google in the `src/google/protobuf/` directory. Unlike custom messages, these types ship with pre-generated code for every supported language and follow strict JSON mapping rules defined in the protobuf specification.

### Core Types Overview

The three most frequently used well-known types are:

- **`google.protobuf.Any`** – A container that holds an arbitrary serialized message as bytes along with a URL that identifies the message type. Defined in `src/google/protobuf/any.proto`.
- **`google.protobuf.Timestamp`** – Represents a point in time independent of time zone or calendar, stored as seconds and nanoseconds since the Unix epoch. Defined in `src/google/protobuf/timestamp.proto`.
- **`google.protobuf.Duration`** – Represents a signed span of time, also using seconds and nanoseconds components. Defined in `src/google/protobuf/duration.proto`.

## Working with google.protobuf.Any

The `Any` type enables dynamic typing by storing the raw bytes of any message alongside a **type URL** that identifies the message's fully qualified name (e.g., `type.googleapis.com/my.package.User`).

### Packing and Unpacking Messages

When using `Any`, you must pack a message before serialization and unpack it after deserialization. The type URL format follows `type.googleapis.com/{fully.qualified.message.name}`.

**Go Example:**

```go
import (
    "google.golang.org/protobuf/types/known/anypb"
    "google.golang.org/protobuf/proto"
)

type User struct {
    Id   int64  `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
    Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
}

func exampleAny() {
    u := &User{Id: 42, Name: "Alice"}
    
    // Pack the message into Any
    anyMsg, _ := anypb.New(u)
    
    // Unpacking requires checking type first
    var unpacked User
    if anypb.UnmarshalTo(anyMsg, &unpacked, proto.UnmarshalOptions{}) == nil {
        // Successfully unpacked
    }
}

```

**Python Example:**

```python
from google.protobuf import any_pb2
from google.protobuf.message import Message

# Assuming User is a generated message class

user = User(id=99, name="Bob")

any_msg = any_pb2.Any()
any_msg.Pack(user)

# Type checking before unpacking

if any_msg.Is(User.DESCRIPTOR):
    unpacked_user = User()
    any_msg.Unpack(unpacked_user)

```

**Java Example:**

```java
import com.google.protobuf.Any;
import com.google.protobuf.Message;

public class AnyExample {
    public static void packAndUnpack(UserProto.User user) {
        // Pack
        Any any = Any.pack(user);
        
        // Unpack with type check
        if (any.is(UserProto.User.class)) {
            UserProto.User unpacked = any.unpack(UserProto.User.class);
        }
    }
}

```

## Handling Timestamps with google.protobuf.Timestamp

`Timestamp` represents time as two fields: `seconds` (int64) since the Unix epoch and `nanos` (int32) for the fractional second component. The valid range spans from `0001-01-01T00:00:00Z` to `9999-12-31T23:59:59.999999999Z`.

**Go Example:**

```go
import (
    "time"
    "google.golang.org/protobuf/types/known/timestamppb"
)

func timestampOps() {
    // Current time
    now := timestamppb.Now()
    
    // From time.Time
    t := time.Date(2024, 3, 2, 12, 0, 0, 0, time.UTC)
    ts := timestamppb.New(t)
    
    // Convert back to time.Time
    goTime := ts.AsTime()
}

```

**Python Example:**

```python
from google.protobuf import timestamp_pb2
from datetime import datetime, timezone

ts = timestamp_pb2.Timestamp()
ts.FromDatetime(datetime.now(timezone.utc))

# Convert back

dt = ts.ToDatetime()

```

**Java Example:**

```java
import com.google.protobuf.Timestamp;
import com.google.protobuf.util.Timestamps;
import java.time.Instant;

public class TimestampExample {
    public static void main() {
        // From milliseconds
        Timestamp now = Timestamps.fromMillis(System.currentTimeMillis());
        
        // To Java Instant
        Instant instant = Timestamps.toInstant(now);
        
        // Add duration
        Timestamp later = Timestamps.add(now, Durations.fromSeconds(3600));
    }
}

```

## Managing Durations with google.protobuf.Duration

`Duration` represents a signed span of time using the same seconds + nanos structure as `Timestamp`. Negative durations are valid. The JSON representation uses a string ending with the letter `s` (e.g., `"300s"` or `"1.500s"`).

**Go Example:**

```go
import (
    "time"
    "google.golang.org/protobuf/types/known/durationpb"
)

func durationOps() {
    // Create from time.Duration
    d := durationpb.New(5 * time.Second)
    
    // Convert to time.Duration
    goDuration := d.AsDuration()
    
    // Arithmetic with timestamps
    future := timestamppb.New(time.Now().Add(d.AsDuration()))
}

```

**Python Example:**

```python
from google.protobuf import duration_pb2
from datetime import timedelta

dur = duration_pb2.Duration()
dur.FromTimedelta(timedelta(hours=2, minutes=30))

# Convert back

td = dur.ToTimedelta()

```

**Java Example:**

```java
import com.google.protobuf.Duration;
import com.google.protobuf.util.Durations;

public class DurationExample {
    public static void main() {
        // From seconds
        Duration hour = Durations.fromSeconds(3600);
        
        // Parse from string
        Duration parsed = Durations.parse("1.5s");
        
        // Add to timestamp
        Timestamp later = Timestamps.add(now, hour);
    }
}

```

## Key Source Files and Implementation Details

The well-known types are defined in the main protobuf repository under `src/google/protobuf/`. These proto files contain extensive comments explaining JSON mapping, valid ranges, and security considerations.

| File | Definition | Key Implementation Details |
|------|------------|---------------------------|
| `src/google/protobuf/any.proto` | `Any` message with `type_url` and `value` fields | Lines 78-101 detail type URL format (`type.googleapis.com/{msg}`) and security considerations for unpacking. Lines 59-68 explain JSON encoding with `@type` field. |
| `src/google/protobuf/timestamp.proto` | `Timestamp` with `seconds` and `nanos` | Lines 8-15 specify valid range (0001-01-01 to 9999-12-31). Lines 59-99 provide language-agnostic construction examples. JSON maps to RFC 3339 strings. |
| `src/google/protobuf/duration.proto` | `Duration` with `seconds` and `nanos` | Lines 50-84 demonstrate arithmetic examples. JSON representation requires string suffix `s` (e.g., "3.000001s"). Valid range is -315,576,000,000 to +315,576,000,000 seconds. |

All three types follow standard protobuf wire encoding: field 1 is always `seconds` or `type_url`, field 2 is `nanos` or `value`.

## Summary

- **Protobuf well-known types** provide standardized, cross-language implementations for `Any`, `Timestamp`, and `Duration` in the `protocolbuffers/protobuf` repository.
- **`google.protobuf.Any`** enables dynamic typing by storing arbitrary messages with a type URL; use `Pack` and `Unpack` methods with type safety checks.
- **`google.protobuf.Timestamp`** represents absolute time as seconds and nanoseconds since Unix epoch; JSON serializes to RFC 3339 format.
- **`google.protobuf.Duration`** represents signed time spans; JSON requires the `s` suffix and supports negative values.
- Source definitions in `src/google/protobuf/any.proto`, `timestamp.proto`, and `duration.proto` guarantee binary compatibility and consistent JSON mapping across all languages.

## Frequently Asked Questions

### What is the difference between Timestamp and Duration in protobuf?

**`google.protobuf.Timestamp`** represents an absolute point in time relative to the Unix epoch (January 1, 1970), while **`google.protobuf.Duration`** represents a signed length of time independent of any starting point. In the source definitions (`timestamp.proto` and `duration.proto`), both use `seconds` and `nanos` fields, but semantically you add durations to timestamps to produce new timestamps.

### How do I safely unpack a message from google.protobuf.Any?

Always verify the type before unpacking to avoid deserialization attacks. In Go, use `anypb.UnmarshalTo` with error checking; in Python, call `any_msg.Is(User.DESCRIPTOR)` before `Unpack()`; in Java, use `any.is(User.class)` before `any.unpack()`. The `any.proto` file (lines 78-101) warns that unpacking arbitrary types can be a security risk if the type URL is not validated.

### Can I use well-known types with JSON serialization?

Yes, protobuf well-known types have canonical JSON representations defined in the protobuf specification. `Timestamp` maps to RFC 3339 strings (e.g., `"2024-03-02T12:34:56.123Z"`), `Duration` maps to strings ending with `s` (e.g., `"300s"`), and `Any` maps to a JSON object containing `@type` and `value` fields. These mappings are documented in the comments of `timestamp.proto` (lines 8-15), `duration.proto`, and `any.proto` (lines 59-68).

### What is the valid range for protobuf Timestamp values?

According to `src/google/protobuf/timestamp.proto` (lines 8-15), valid timestamps range from `0001-01-01T00:00:00Z` to `9999-12-31T23:59:59.999999999Z`. This represents a range of approximately 10,000 years. The `seconds` field must be within this range, and `nanos` must be between 0 and 999,999,999 inclusive (or negative for negative timestamps in the case of Duration).