# class Time::Location

- Time::Location
- Reference
- Object

##
Overview

`Location` maps time instants to the zone in use at that time. It typically represents the collection of time offsets observed in a certain geographical area.

It contains a list of zone offsets and rules for transitioning between them.

If a location has only one offset (such as `UTC`) it is considered fixed.

A `Location` instance is usually retrieved by name using `Time::Location.load`. It loads the zone offsets and transitioning rules from the time zone database provided by the operating system.

    location = Time::Location.load("Europe/Berlin")
    location # => #<Time::Location Europe/Berlin>
    time = Time.local(2016, 2, 15, 21, 1, 10, location: location)
    time # => 2016-02-15 21:01:10+01:00[Europe/Berlin]

A custom time zone database can be configured through the environment variable `ZONEINFO`. See `.load` for details.

###
Fixed Offset

A fixed offset location is created using `Time::Location.fixed`:

    location = Time::Location.fixed(3600)
    location       # => #<Time::Location +01:00>
    location.zones # => [#<Time::Location::Zone +01:00 (0s) STD>]

###
Local Time Zone

The local time zone can be accessed as `Time::Location.local`.

It is initially configured according to system environment settings, but its value can be changed:

    location = Time::Location.local
    Time::Location.local = Time::Location.load("America/New_York")

##
Direct Known Subclasses

- Time::TZLocation
- Time::WindowsLocation

##
Defined in:

json/to_json.cr
time/location.cr
time/location/loader.cr
yaml/to_yaml.cr

##
Constant Summary

UTC = `new("UTC", [Zone::UTC])`

  Describes the Coordinated Universal Time (UTC).

  The only time zone offset in this location is `Zone::UTC`.

##
Constructors

- .fixed(name : String, offset : Int32) : Location

  Creates a `Location` instance named name with fixed offset in seconds from UTC.

- .fixed(offset : Int32) : self

  Creates a `Location` instance with fixed offset in seconds from UTC.

- .load(name : String) : Location

  Loads the `Location` with the given name.

- .load_local : Location

  Loads the local time zone according to the current application environment.

- .local : Location

  Returns the `Location` representing the application's local time zone.

- .new(ctx : YAML::ParseContext, node : YAML::Nodes::Node)
- .new(pull : JSON::PullParser)

##
Class Method Summary

- .from_json_object_key?(key : String) : Time::Location
- .load?(name : String) : Location | Nil

  Loads the `Location` with the given name.

- .local=(local : Location)

  Returns the `Location` representing the application's local time zone.

- .posix_tz(name : String, str : String) : TZLocation

  Creates a `Location` instance named name with the given POSIX TZ string str, as defined in POSIX.1-2024 Section 8.3.

##
Instance Method Summary

- #==(other : self)

  Returns `true` if other is equal to `self`.

- #fixed? : Bool

  Returns `true` if this location has a fixed offset.

- #hash(hasher)

  Returns `true` if other is equal to `self`.

- #inspect(io : IO) : Nil

  Appends a String representation of this object which includes its class name, its object address and the values of all instance variables.

- #local? : Bool

  Returns `true` if this location equals to `Time::Location.local`.

- #lookup(time : Time) : Zone

  Returns the time zone offset observed at time.

- #lookup(unix_seconds : Int) : Zone

  Returns the time zone offset observed at unix_seconds.

- #name : String

  Returns the name of this location.

- #to_json(json : JSON::Builder) : Nil
- #to_s(io : IO) : Nil

  Prints `#name` to io.

- #to_yaml(yaml : YAML::Nodes::Builder) : Nil
- #utc? : Bool

  Returns `true` if this location equals to `UTC`.

- #zones : Array(Zone)

  Returns the array of time zone offsets (`Zone`) used in this time zone.

### Instance methods inherited from class `Reference`

==(other : self)
==(other : JSON::Any)
==(other : YAML::Any)
==(other) ==, dup dup, hash(hasher) hash, initialize initialize, inspect(io : IO) : Nil inspect, object_id : UInt64 object_id, pretty_print(pp) : Nil pretty_print, same?(other : Reference) : Bool
same?(other : Nil) same?, to_s(io : IO) : Nil to_s

### Constructor methods inherited from class `Reference`

new new, unsafe_construct(address : Pointer, *args, **opts) : self unsafe_construct

### Class methods inherited from class `Reference`

pre_initialize(address : Pointer) pre_initialize

### Instance methods inherited from class `Object`

! : Bool !, !=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other) ===, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash hash, in?(collection : Object) : Bool
in?(*values : Object) : Bool in?, inspect(io : IO) : Nil
inspect : String inspect, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String to_json, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil to_pretty_json, to_s(io : IO) : Nil
to_s : String to_s, to_yaml(io : IO) : Nil
to_yaml : String to_yaml, try(&) try, unsafe_as(type : T.class) forall T unsafe_as

### Class methods inherited from class `Object`

from_json(string_or_io : String | IO, root : String)
from_json(string_or_io : String | IO) from_json, from_yaml(string_or_io : String | IO) from_yaml

### Macros inherited from class `Object`

class_getter(*names, &block) class_getter, class_getter!(*names) class_getter!, class_getter?(*names, &block) class_getter?, class_property(*names, &block) class_property, class_property!(*names) class_property!, class_property?(*names, &block) class_property?, class_setter(*names) class_setter, def_clone def_clone, def_equals(*fields) def_equals, def_equals_and_hash(*fields) def_equals_and_hash, def_hash(*fields) def_hash, delegate(*methods, to object) delegate, forward_missing_to(delegate) forward_missing_to, getter(*names, &block) getter, getter!(*names) getter!, getter?(*names, &block) getter?, property(*names, &block) property, property!(*names) property!, property?(*names, &block) property?, setter(*names) setter

##
Constructor Detail

def self.fixed(name : String, offset : Int32) : Location #

Creates a `Location` instance named name with fixed offset in seconds from UTC.

def self.fixed(offset : Int32) : self #

Creates a `Location` instance with fixed offset in seconds from UTC.

The formatted offset is used as name.

def self.load(name : String) : Location #

Loads the `Location` with the given name.

    location = Time::Location.load("Europe/Berlin")

name is understood to be a location name in the IANA Time Zone database, such as `"America/New_York"`. As special cases, `"UTC"`, `"Etc/UTC"` and empty string (`""`) return `Location::UTC`, and `"Local"` returns `Location.local`.

The implementation uses a list of system-specific paths to look for a time zone database. The first time zone database entry matching the given name that is successfully loaded and parsed is returned. Typical paths on Unix-based operating systems are `/usr/share/zoneinfo/`, `/usr/share/lib/zoneinfo/`, or `/usr/lib/locale/TZ/`.

A time zone database may not be present on all systems, especially non-Unix systems. In this case, you may need to distribute a copy of the database with an application that depends on time zone data being available.

A custom lookup path can be set as environment variable `ZONEINFO`. The path can point to the root of a directory structure or an uncompressed ZIP file, each representing the time zone database using files and folders of the expected names.

Example:

    # This tries to load the file `/usr/share/zoneinfo/Custom/Location`
    ENV["ZONEINFO"] = "/usr/share/zoneinfo/"
    Time::Location.load("Custom/Location")

    # This tries to load the file `Custom/Location` in the uncompressed ZIP
    # file at `/path/to/zoneinfo.zip`
    ENV["ZONEINFO"] = "/path/to/zoneinfo.zip"
    Time::Location.load("Custom/Location")

If the location name cannot be found, `InvalidLocationNameError` is raised. If the loader encounters a format error in the time zone database, `InvalidTZDataError` is raised.

Files are cached based on the modification time, so subsequent request for the same location name will most likely return the same instance of `Location`, unless the time zone database has been updated in between.

- `.load?` returns `nil` if the location is unavailable.

def self.load_local : Location #

Loads the local time zone according to the current application environment.

The environment variable `ENV["TZ"]` is consulted for finding the time zone to use.

- `"UTC"`, `"Etc/UTC"` and empty string (`""`) return `Location::UTC`.
- POSIX TZ strings (such as `"EST5EDT,M3.2.0,M11.1.0"`) are parsed using `Location.posix_tz`.
- Values beginning with a colon are implementation-defined according to POSIX, and not supported in Crystal.
- Any other value (such as `"Europe/Berlin"`) is tried to be resolved using `Location.load`.
- If `ENV["TZ"]` is not set, the system's local time zone data will be used (`/etc/localtime` on unix-based systems).
- If no time zone data could be found (i.e. the previous methods failed), `Location::UTC` is returned.

def self.local : Location #

Returns the `Location` representing the application's local time zone.

`Time` uses this property as default value for most method arguments expecting a `Location`.

The initial value depends on the current application environment, see `.load_local` for details.

The value can be changed to overwrite the system default:

    Time.local.location # => #<Time::Location America/New_York>
    Time::Location.local = Time::Location.load("Europe/Berlin")
    Time.local.location # => #<Time::Location Europe/Berlin>

def self.new(ctx : YAML::ParseContext, node : YAML::Nodes::Node) #
def self.new(pull : JSON::PullParser) #

##
Class Method Detail

def self.from_json_object_key?(key : String) : Time::Location #
def self.load?(name : String) : Location | Nil #

Loads the `Location` with the given name.

    location = Time::Location.load("Europe/Berlin")

name is understood to be a location name in the IANA Time Zone database, such as `"America/New_York"`. As special cases, `"UTC"`, `"Etc/UTC"` and empty string (`""`) return `Location::UTC`, and `"Local"` returns `Location.local`.

The implementation uses a list of system-specific paths to look for a time zone database. The first time zone database entry matching the given name that is successfully loaded and parsed is returned. Typical paths on Unix-based operating systems are `/usr/share/zoneinfo/`, `/usr/share/lib/zoneinfo/`, or `/usr/lib/locale/TZ/`.

A time zone database may not be present on all systems, especially non-Unix systems. In this case, you may need to distribute a copy of the database with an application that depends on time zone data being available.

A custom lookup path can be set as environment variable `ZONEINFO`. The path can point to the root of a directory structure or an uncompressed ZIP file, each representing the time zone database using files and folders of the expected names.

Example:

    # This tries to load the file `/usr/share/zoneinfo/Custom/Location`
    ENV["ZONEINFO"] = "/usr/share/zoneinfo/"
    Time::Location.load("Custom/Location")

    # This tries to load the file `Custom/Location` in the uncompressed ZIP
    # file at `/path/to/zoneinfo.zip`
    ENV["ZONEINFO"] = "/path/to/zoneinfo.zip"
    Time::Location.load("Custom/Location")

If the location name cannot be found, `InvalidLocationNameError` is raised. If the loader encounters a format error in the time zone database, `InvalidTZDataError` is raised.

Files are cached based on the modification time, so subsequent request for the same location name will most likely return the same instance of `Location`, unless the time zone database has been updated in between.

- `.load?` returns `nil` if the location is unavailable.

Returns `nil` if the location is unavailable. Raises `InvalidLocationNameError` if the name is invalid. Raises `InvalidTZDataError` if the loader encounters a format error in the time zone database.

- `.load` raises if the location is unavailable.

def self.local=(local : Location) #

Returns the `Location` representing the application's local time zone.

`Time` uses this property as default value for most method arguments expecting a `Location`.

The initial value depends on the current application environment, see `.load_local` for details.

The value can be changed to overwrite the system default:

    Time.local.location # => #<Time::Location America/New_York>
    Time::Location.local = Time::Location.load("Europe/Berlin")
    Time.local.location # => #<Time::Location Europe/Berlin>

def self.posix_tz(name : String, str : String) : TZLocation #

Creates a `Location` instance named name with the given POSIX TZ string str, as defined in POSIX.1-2024 Section 8.3.

str must begin with a standard time designator followed by a time offset; implementation-defined TZ strings beginning with a colon, as well as names from the time zone database, are not supported.

If str designates a daylight saving time, then the transition times must also be present. A TZ string like `"PST8PDT"` alone is considered invalid, since no default transition rules are assumed.

    location = Time::Location.posix_tz("America/New_York", "EST5EDT,M3.2.0,M11.1.0")
    Time.utc(2025, 3, 9, 6).in(location)  # => 2025-03-09 01:00:00.0 -05:00 America/New_York
    Time.utc(2025, 3, 9, 7).in(location)  # => 2025-03-09 03:00:00.0 -04:00 America/New_York
    Time.utc(2025, 11, 2, 5).in(location) # => 2025-11-02 01:00:00.0 -04:00 America/New_York
    Time.utc(2025, 11, 2, 6).in(location) # => 2025-11-02 01:00:00.0 -05:00 America/New_York

##
Instance Method Detail

def ==(other : self) #

Returns `true` if other is equal to `self`.

Two `Location` instances are considered equal if they have the same name, offset zones and transition rules.

def fixed? : Bool #

Returns `true` if this location has a fixed offset.

Locations returned by `Location.posix_tz` have a fixed offset if the TZ string specifies either no daylight saving time at all, or an all-year daylight saving time (e.g. `"EST5EDT,0/0,J365/25"`).

def hash(hasher) #

Returns `true` if other is equal to `self`.

Two `Location` instances are considered equal if they have the same name, offset zones and transition rules.

def inspect(io : IO) : Nil #
Description copied from class Reference

Appends a String representation of this object which includes its class name, its object address and the values of all instance variables.

    class Person
      def initialize(@name : String, @age : Int32)
      end
    end

    Person.new("John", 32).inspect # => #<Person:0x10fd31f20 @name="John", @age=32>

def local? : Bool #

Returns `true` if this location equals to `Time::Location.local`.

def lookup(time : Time) : Zone #

Returns the time zone offset observed at time.

def lookup(unix_seconds : Int) : Zone #

Returns the time zone offset observed at unix_seconds.

unix_seconds expresses the number of seconds since UNIX epoch (`1970-01-01 00:00:00Z`).

def name : String #

Returns the name of this location.

It usually consists of a continent and city name separated by a slash, for example `Europe/Berlin`.

def to_json(json : JSON::Builder) : Nil #
def to_s(io : IO) : Nil #

Prints `#name` to io.

def to_yaml(yaml : YAML::Nodes::Builder) : Nil #
def utc? : Bool #

Returns `true` if this location equals to `UTC`.

def zones : Array(Zone) #

Returns the array of time zone offsets (`Zone`) used in this time zone.