Skip to content

Commit b07c836

Browse files
committed
updates for version 1
1 parent f5550db commit b07c836

File tree

10 files changed

+95
-73
lines changed

10 files changed

+95
-73
lines changed

README.md

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
# tzif
22

3-
<!--#
4-
[![Package Version](https://img.shields.io/hexpm/v/timezone)](https://hex.pm/packages/timezone)
5-
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/timezone/)
6-
-->
3+
[![Package Version](https://img.shields.io/hexpm/v/tzif)](https://hex.pm/packages/tzif)
4+
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/tzif/)
75

86
Time zone support for Gleam time using the IANA Time Zone Database.
97
This package loads the time zone database from the standard location
@@ -18,13 +16,18 @@ of day in the given time zone.
1816
>
1917
> --- Louis Pilfold
2018
21-
To use, add the following entry in your `gleam.toml` file dependencies:
22-
19+
Add to your project with the command:
2320
```
24-
tzif = { git = "[email protected]:devries/timezone.git", ref = "main" }
21+
gleam add tzif@1
2522
```
2623

2724
# Using the Package
25+
There are three modules in the `tzif` package:
26+
- `tzif/database` has utilities for loading the IANA Time Zone database.
27+
- `tzif/tzcalendar` has utilities for converting a [gleam_time](https://hexdocs.pm/gleam_time/)
28+
timestamp into date and time of day in a time zone.
29+
- `tzif/parser` has functions and records for parsing TZif formatted data.
30+
2831
The most straightforward use would be to load the database from the default
2932
location on the operating system, and then obtain a timestamp using the
3033
[gleam_time](https://hexdocs.pm/gleam_time/) package, and convert that timestamp
@@ -43,27 +46,30 @@ pub fn main() {
4346
let now = timestamp.system_time()
4447
4548
// Load the database from the operating system
46-
let db = database.load_from_os()
47-
48-
case tzcalendar.get_time_and_zone(now, "America/New_York", db) {
49-
Ok(time_and_zone) -> {
50-
// Successfully converted time to the requested time zone
51-
io.println(
52-
int.to_string(time_and_zone.time_of_day.hours)
53-
|> string.pad_start(2, "0")
54-
<> ":"
55-
<> int.to_string(time_and_zone.time_of_day.minutes)
56-
|> string.pad_start(2, "0")
57-
<> ":"
58-
<> int.to_string(time_and_zone.time_of_day.seconds)
59-
|> string.pad_start(2, "0")
60-
<> " "
61-
<> time_and_zone.designation
62-
)
49+
case database.load_from_os() {
50+
Ok(db) -> {
51+
case tzcalendar.to_time_and_zone(now, "America/New_York", db) {
52+
Ok(time_and_zone) -> {
53+
// Successfully converted time to the requested time zone
54+
io.println(
55+
int.to_string(time_and_zone.time_of_day.hours)
56+
|> string.pad_start(2, "0")
57+
<> ":"
58+
<> int.to_string(time_and_zone.time_of_day.minutes)
59+
|> string.pad_start(2, "0")
60+
<> ":"
61+
<> int.to_string(time_and_zone.time_of_day.seconds)
62+
|> string.pad_start(2, "0")
63+
<> " "
64+
<> time_and_zone.designation
65+
)
66+
}
67+
Error(database.ZoneNotFound) -> io.println("Time zone not found")
68+
Error(database.ProcessingError) ->
69+
io.println("Error processing time zone conversion")
70+
}
6371
}
64-
Error(database.ZoneNotFound) -> io.println("Time zone not found")
65-
Error(database.ProcessingError) -> io.println("Error processing time zone conversion")
66-
}
72+
Error(Nil) -> io.println("No parsable TZif files found.")
6773
}
6874
```
6975
If you are on windows and have installed the IANA Time Zone Database, or want

examples/simple/src/simple.gleam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub fn main() {
1313
Error(Nil) ->
1414
io.println("No parsable TZif files found in default location.")
1515
Ok(db) -> {
16-
case tzcalendar.get_time_and_zone(now, "America/New_York", db) {
16+
case tzcalendar.to_time_and_zone(now, "America/New_York", db) {
1717
Ok(time_and_zone) -> {
1818
// Successfully converted time to the requested time zone
1919
io.println(

examples/time_now/src/time_now.gleam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ fn print_all_times(now: timestamp.Timestamp) -> Result(Nil, Nil) {
2121

2222
database.get_available_timezones(db)
2323
|> list.map(fn(zone_name) {
24-
case tzcalendar.get_time_and_zone(now, zone_name, db) {
24+
case tzcalendar.to_time_and_zone(now, zone_name, db) {
2525
Ok(tiz) ->
2626
io.println(
2727
string.pad_end(zone_name <> ":", 40, " ") <> format_time(tiz),

gleam.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name = "tzif"
2-
version = "0.2.0"
2+
version = "1.0.0"
33

44
# Fill out these fields if you intend to generate HTML documentation or publish
55
# your project to the Hex package manager.

src/tzif/database.gleam

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import gleam/string
1010
import gleam/time/duration.{type Duration}
1111
import gleam/time/timestamp
1212
import simplifile
13-
import tzif/tzparser
13+
import tzif/parser
1414

1515
/// Time Zone Database record. This is typically created by
1616
/// loading from the operating system with the `load_from_os`
@@ -20,7 +20,7 @@ import tzif/tzparser
2020
pub opaque type TzDatabase {
2121
TzDatabase(
2222
zone_names: List(String),
23-
zone_data: dict.Dict(String, tzparser.TzFile),
23+
zone_data: dict.Dict(String, parser.TzFile),
2424
)
2525
}
2626

@@ -82,7 +82,7 @@ pub fn new() -> TzDatabase {
8282
pub fn add_tzfile(
8383
db: TzDatabase,
8484
zone_name: String,
85-
tzfile: tzparser.TzFile,
85+
tzfile: parser.TzFile,
8686
) -> TzDatabase {
8787
let namelist = case dict.has_key(db.zone_data, zone_name) {
8888
True -> db.zone_names
@@ -94,7 +94,7 @@ pub fn add_tzfile(
9494
fn process_tzfile(
9595
filename: String,
9696
components_to_drop: Int,
97-
) -> Result(#(String, tzparser.TzFile), Nil) {
97+
) -> Result(#(String, parser.TzFile), Nil) {
9898
let zone_name =
9999
filepath.split(filename)
100100
|> list.drop(components_to_drop)
@@ -103,9 +103,7 @@ fn process_tzfile(
103103
use tzdata <- result.try(
104104
simplifile.read_bits(filename) |> result.replace_error(Nil),
105105
)
106-
use timeinfo <- result.try(
107-
tzparser.parse(tzdata) |> result.replace_error(Nil),
108-
)
106+
use timeinfo <- result.try(parser.parse(tzdata) |> result.replace_error(Nil))
109107

110108
Ok(#(zone_name, timeinfo))
111109
}
@@ -117,12 +115,10 @@ pub fn get_available_timezones(db: TzDatabase) -> List(String) {
117115
}
118116

119117
/// Time zone parameters record.
120-
/// - `offset` is the offset from UTC.
118+
/// - `offset` is the offset from UTC using [gleam_time](https://hexdocs.pm/gleam_time/gleam/time/duration.html#Duration)
119+
/// `Duration`.
121120
/// - `is_dst` indicates if it is daylight savings time
122121
/// - `designation` is the time zone designation
123-
/// This is the same information provided by a `TtInfo` record, but
124-
/// modified to use the [gleam_time](https://hexdocs.pm/gleam_time/index.html)
125-
/// duration type and a boolean for the daylight saving time indication.
126122
pub type ZoneParameters {
127123
ZoneParameters(offset: Duration, is_dst: Bool, designation: String)
128124
}
@@ -223,7 +219,7 @@ type TtSlice {
223219
}
224220

225221
// Turn time zone fields into a list of timezone information slices
226-
fn create_slices(fields: tzparser.TzFileFields) -> List(TtSlice) {
222+
fn create_slices(fields: parser.TzFileFields) -> List(TtSlice) {
227223
let infos =
228224
list.zip(fields.ttinfos, fields.designations)
229225
|> list.index_map(fn(tup, idx) { #(idx, tup) })
@@ -246,7 +242,7 @@ fn create_slices(fields: tzparser.TzFileFields) -> List(TtSlice) {
246242
|> result.values
247243
}
248244

249-
fn default_slice(fields: tzparser.TzFileFields) -> Result(TtSlice, Nil) {
245+
fn default_slice(fields: parser.TzFileFields) -> Result(TtSlice, Nil) {
250246
use ttinfo <- result.try(list.first(fields.ttinfos))
251247
use designation <- result.try(list.first(fields.designations))
252248
let isdst = case ttinfo.isdst {

src/tzif/tzcalendar.gleam

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub type TimeAndZone {
5050
/// let ts = timestamp.from_unix_seconds(1_758_223_300)
5151
/// let assert Ok(db) = database.load_from_os()
5252
///
53-
/// get_time_and_zone(ts, "America/New_York", db)
53+
/// to_time_and_zone(ts, "America/New_York", db)
5454
/// // Ok(TimeInZone(
5555
/// // Date(2025, September, 18),
5656
/// // TimeOfDay(15, 21, 40, 0),
@@ -59,7 +59,7 @@ pub type TimeAndZone {
5959
/// // True,
6060
/// // ))
6161
/// ```
62-
pub fn get_time_and_zone(
62+
pub fn to_time_and_zone(
6363
ts: Timestamp,
6464
zone_name: String,
6565
db: TzDatabase,
@@ -104,7 +104,7 @@ pub fn to_calendar(
104104
zone_name: String,
105105
db: TzDatabase,
106106
) -> Result(#(calendar.Date, calendar.TimeOfDay), TzDatabaseError) {
107-
use tiz <- result.map(get_time_and_zone(ts, zone_name, db))
107+
use tiz <- result.map(to_time_and_zone(ts, zone_name, db))
108108

109109
#(tiz.date, tiz.time_of_day)
110110
}

test/tzif/database_test.gleam

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import gleam/list
33
import gleam/time/duration
44
import gleam/time/timestamp
55
import tzif/database
6-
import tzif/tzparser
6+
import tzif/parser
77

88
const tzsample = "VFppZjIAAAAAAAAAAAAAAAAAAAAAAAAGAAAABgAAAAAAAADsAAAABgAAABSAAAAAnqYecJ+662CghgBwoZrNYKJl4nCjg+ngpGqucKU1p2CmU8rwpxWJYKgzrPCo/qXgqhOO8Kreh+Cr83DwrL5p4K3TUvCunkvgr7M08LB+LeCxnFFwsmdKYLN8M3C0RyxgtVwVcLYnDmC3O/dwuAbwYLkb2XC55tJguwT18LvGtGC85Nfwva/Q4L7EufC/j7LgwKSb8MFvlODChH3ww0924MRkX/DFL1jgxk18cMcPOuDILV5wyPhXYMoNQHDK2Dlgy4jwcNIj9HDSYPvg03Xk8NRA3eDVVcbw1iC/4Nc1qPDYAKHg2RWK8Nngg+Da/qdw28Bl4NzeiXDdqYJg3r5rcN+JZGDgnk1w4WlGYOJ+L3DjSShg5F4RcOVXLuDmRy3w5zcQ4OgnD/DpFvLg6gbx8Or21ODr5tPw7Na24O3GtfDuv9Ng76/ScPCftWDxj7Rw8n+XYPNvlnD0X3lg9U94cPY/W2D3L1pw+Ch34PkPPHD6CFng+vhY8PvoO+D82Drw/cgd4P64HPD/p//gAJf+8AGH4eACd+DwA3D+YARg/XAFUOBgBkDfcAcwwmAHjRlwCRCkYAmtlPAK8IZgC+CFcAzZouANwGdwDrmE4A+pg/AQmWbgEYll8BJ5SOATaUfwFFkq4BVJKfAWOQzgFykL8BgiKWAZCO3wGgILYBryCnAb4e1gHNHscB3Bz2Aesc5wH6GxYCB2APAhgZNgIlXi8CNqr+AkNcTwJUqR4CYVpvAnKnPgJ/7DcCkKVeAp3qVwKuo34Cu+h3As01RgLZ5pcC6zNmAvfktwMJMYYDFnZ/AycvpgM0dJ8DRS3GA1JyvwNjK+YDcHDfA4G9rgOObv8Dn7vOA6xtHwO9ue4Dyv7nA9u4DgPo/QcD+bYuBAb7JwQYR/YEJPlHBDZGFgRC92cEVEQ2BF86jwRy1f4EfTivBJDUHgSbNs8ErtI+BLnIlwTNZAYE18a3BOtiJgT1xNcFCWBGBRPC9wUnXmYFMcEXBUVchgVPvzcFY1qmBW5Q/wWB7G4FjE8fBZ/qjgWqTT8FveiuBchLXwXb5s4F5kl/Bfnk7gYE20cGGHa2BiLZZwY2dNYGQNeHBlRy9gZe1acGcnEWBnzTxwaQbzYGmtHnBq5tVga5Y68GzP8eBtdhzwbq/T4G9V/vBwj7XgcTXg8HJvl+BzFcLwdE954HT+33B2OJZgdt7BcHgYeGB4vqNwefhaYHqehXB72DxgfH5ncH24HmB+Xklwf5gAYAMBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIEBQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgEC//+6ngAA///HwAEE//+5sAAI//+5sAAI///HwAEM///HwAEQTE1UAEVEVABFU1QARVdUAEVQVAAAAAABAAEAAAABAAFUWmlmMgAAAAAAAAAAAAAAAAAAAAAAAAYAAAAGAAAAAAAAAOwAAAAGAAAAFP////9eA/CQ/////56mHnD/////n7rrYP////+ghgBw/////6GazWD/////omXicP////+jg+ng/////6RqrnD/////pTWnYP////+mU8rw/////6cViWD/////qDOs8P////+o/qXg/////6oTjvD/////qt6H4P////+r83Dw/////6y+aeD/////rdNS8P////+unkvg/////6+zNPD/////sH4t4P////+xnFFw/////7JnSmD/////s3wzcP////+0Ryxg/////7VcFXD/////ticOYP////+3O/dw/////7gG8GD/////uRvZcP////+55tJg/////7sE9fD/////u8a0YP////+85Nfw/////72v0OD/////vsS58P////+/j7Lg/////8Ckm/D/////wW+U4P/////ChH3w/////8NPduD/////xGRf8P/////FL1jg/////8ZNfHD/////xw864P/////ILV5w/////8j4V2D/////yg1AcP/////K2Dlg/////8uI8HD/////0iP0cP/////SYPvg/////9N15PD/////1EDd4P/////VVcbw/////9Ygv+D/////1zWo8P/////YAKHg/////9kVivD/////2eCD4P/////a/qdw/////9vAZeD/////3N6JcP/////dqYJg/////96+a3D/////34lkYP/////gnk1w/////+FpRmD/////4n4vcP/////jSShg/////+ReEXD/////5Vcu4P/////mRy3w/////+c3EOD/////6CcP8P/////pFvLg/////+oG8fD/////6vbU4P/////r5tPw/////+zWtuD/////7ca18P/////uv9Ng/////++v0nD/////8J+1YP/////xj7Rw//////J/l2D/////82+WcP/////0X3lg//////VPeHD/////9j9bYP/////3L1pw//////god+D/////+Q88cP/////6CFng//////r4WPD/////++g74P/////82Drw//////3IHeD//////rgc8P//////p//gAAAAAACX/vAAAAAAAYfh4AAAAAACd+DwAAAAAANw/mAAAAAABGD9cAAAAAAFUOBgAAAAAAZA33AAAAAABzDCYAAAAAAHjRlwAAAAAAkQpGAAAAAACa2U8AAAAAAK8IZgAAAAAAvghXAAAAAADNmi4AAAAAANwGdwAAAAAA65hOAAAAAAD6mD8AAAAAAQmWbgAAAAABGJZfAAAAAAEnlI4AAAAAATaUfwAAAAABRZKuAAAAAAFUkp8AAAAAAWOQzgAAAAABcpC/AAAAAAGCIpYAAAAAAZCO3wAAAAABoCC2AAAAAAGvIKcAAAAAAb4e1gAAAAABzR7HAAAAAAHcHPYAAAAAAesc5wAAAAAB+hsWAAAAAAIHYA8AAAAAAhgZNgAAAAACJV4vAAAAAAI2qv4AAAAAAkNcTwAAAAACVKkeAAAAAAJhWm8AAAAAAnKnPgAAAAACf+w3AAAAAAKQpV4AAAAAAp3qVwAAAAACrqN+AAAAAAK76HcAAAAAAs01RgAAAAAC2eaXAAAAAALrM2YAAAAAAvfktwAAAAADCTGGAAAAAAMWdn8AAAAAAycvpgAAAAADNHSfAAAAAANFLcYAAAAAA1JyvwAAAAADYyvmAAAAAANwcN8AAAAAA4G9rgAAAAADjm7/AAAAAAOfu84AAAAAA6xtHwAAAAADvbnuAAAAAAPK/ucAAAAAA9u4DgAAAAAD6P0HAAAAAAP5ti4AAAAABAb7JwAAAAAEGEf2AAAAAAQk+UcAAAAABDZGFgAAAAAEQvdnAAAAAARURDYAAAAABF86jwAAAAAEctX+AAAAAAR9OK8AAAAABJDUHgAAAAAEmzbPAAAAAASu0j4AAAAABLnIlwAAAAAEzWQGAAAAAATXxrcAAAAABOtiJgAAAAAE9cTXAAAAAAUJYEYAAAAABRPC9wAAAAAFJ15mAAAAAAUxwRcAAAAABUVchgAAAAAFT783AAAAAAVjWqYAAAAABW5Q/wAAAAAFgexuAAAAAAWMTx8AAAAABZ/qjgAAAAAFqk0/AAAAAAW96K4AAAAABchLXwAAAAAF2+bOAAAAAAXmSX8AAAAABfnk7gAAAAAGBNtHAAAAAAYYdrYAAAAABiLZZwAAAAAGNnTWAAAAAAZA14cAAAAABlRy9gAAAAAGXtWnAAAAAAZycRYAAAAABnzTxwAAAAAGkG82AAAAAAaa0ecAAAAABq5tVgAAAAAGuWOvAAAAAAbM/x4AAAAABtdhzwAAAAAG6v0+AAAAAAb1X+8AAAAABwj7XgAAAAAHE14PAAAAAAcm+X4AAAAABzFcLwAAAAAHRPeeAAAAAAdP7fcAAAAAB2OJZgAAAAAHbewXAAAAAAeBh4YAAAAAB4vqNwAAAAAHn4WmAAAAAAep6FcAAAAAB72DxgAAAAAHx+Z3AAAAAAfbgeYAAAAAB+XklwAAAAAH+YAGADAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECBAUCAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAv//up4AAP//x8ABBP//ubAACP//ubAACP//x8ABDP//x8ABEExNVABFRFQARVNUAEVXVABFUFQAAAAAAQABAAAAAQABCkVTVDVFRFQsTTMuMi4wLE0xMS4xLjAK"
99

@@ -13,13 +13,13 @@ const right_utc_sample = "VFppZjIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsAAAABAAAAAQ
1313

1414
fn get_database() -> database.TzDatabase {
1515
let assert Ok(tzdata) = bit_array.base64_decode(tzsample)
16-
let assert Ok(tz_ny) = tzparser.parse(tzdata)
16+
let assert Ok(tz_ny) = parser.parse(tzdata)
1717

1818
let assert Ok(tzdata2) = bit_array.base64_decode(tzsample2)
19-
let assert Ok(tz_utc) = tzparser.parse(tzdata2)
19+
let assert Ok(tz_utc) = parser.parse(tzdata2)
2020

2121
let assert Ok(tzdata3) = bit_array.base64_decode(right_utc_sample)
22-
let assert Ok(tz_right_utc) = tzparser.parse(tzdata3)
22+
let assert Ok(tz_right_utc) = parser.parse(tzdata3)
2323

2424
database.new()
2525
|> database.add_tzfile("America/New_York", tz_ny)

0 commit comments

Comments
 (0)