ical

package module
v0.4.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 10, 2020 License: MIT Imports: 9 Imported by: 0

README

iCalendar (.ics) parser

Test

This package parses iCalendars specified by RFC 5545.

Features

  • Concurrent lexing & parsing
  • Buffered lexer
  • allows CRLF & LF line breaks
  • Component validation

Implemented components

Install

go get github.com/bounoable/ical

Usage

View the docs for more examples.

package main

import (
  "fmt"
  "os"
  "github.com/bounoable/ical"
)

func main() {
  f, err := os.Open("/path/to/calendar.ics")
  if err != nil {
    panic(err)
  }
  defer f.Close()

  cal, err := ical.Parse(f)
  if err != nil {
    panic(err)
  }

  // use events
  for _, evt := range cal.Events {
    fmt.Println(evt)
  }
}

Context

You can attach a context.Context to both the lexer & parser via an option:

package main

import (
  "context"
  "os"
  "time"
  "github.com/bounoable/ical"
)

func main() {
  f, err := os.Open("/path/to/calendar.ics")
  if err != nil {
    panic(err)
  }
  defer f.Close()

  // cancel the lexing & parsing after 3 seconds
  ctx, cancel := context.WithTimeout(time.Second * 3)
  defer cancel()

  cal, err := ical.Parse(f, ical.Context(ctx))
  if err != nil {
    panic(err)
  }
}

Strict line breaks

By default, the lexer allows the input to use LF linebreaks instead of CRLF, because many iCalendars out there don't fully adhere to the spec. You can however enforce the use of CRLF line breaks via an option:

package main

import (
  "os"
  "github.com/bounoable/ical"
  "github.com/bounoable/ical/lex"
)

func main() {
  f, err := os.Open("/path/to/calendar.ics")
  if err != nil {
    panic(err)
  }
  defer f.Close()

  cal, err := ical.Parse(f, ical.LexWith(
    lex.StrictLineBreaks, // lexer option
  ))

  if err != nil {
    panic(err)
  }
}

Timezones

You can explicitly set the *time.Location that is used to parse DATE & DATE-TIME values that would otherwise be parsed in local time. This option overrides TZID parameters in the iCalendar.

package main

import (
  "os"
  "time"
  "github.com/bounoable/ical"
  "github.com/bounoable/ical/parse"
)

func main() {
  f, err := os.Open("/path/to/calendar.ics")
  if err != nil {
    panic(err)
  }
  defer f.Close()

  loc, err := time.LoadLocation("Europe/Berlin")
  if err != nil {
    panic(err)
  }

  cal, err := ical.Parse(f, ical.ParseWith(
    parse.Location(loc),
  ))

  if err != nil {
    panic(err)
  }
}

Lexing & parsing

Both the lexer & parser are being exposed as separate packages, so you could do the following:

package main

import (
  "fmt"
  "os"
  "github.com/bounoable/ical/lex"
  "github.com/bounoable/ical/parse"
)

func main() {
  f, err := os.Open("/path/to/calendar.ics")
  if err != nil {
    panic(err)
  }
  defer f.Close()

  items := lex.Reader(f) // items is a channel of lexer items/tokens

  cal, err := parse.Items(items) // pass the items channel to the parser
  if err != nil {
    panic(err)
  }

  for _, evt := range cal.Events {
    fmt.Println(evt)
  }
}

Documentation

Overview

Package ical parses iCalendar (.ics) files.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Encode added in v0.3.0

func Encode(cal Calendar, w io.Writer) error

Encode writes the .ics file for cal into w.

Example
package main

import (
	"os"

	"github.com/bounoable/ical"
)

func main() {
	f, err := os.Open("/path/to/calendar.ics")
	if err != nil {
		panic(err)
	}
	defer f.Close()

	cal, err := ical.Parse(f)
	if err != nil {
		panic(err)
	}

	out, err := os.Create("/path/to/new_calendar.ics")
	if err != nil {
		panic(err)
	}

	if err := ical.Encode(cal, out); err != nil {
		panic(err)
	}
}
Output:

func Marshal added in v0.3.1

func Marshal(cal Calendar) ([]byte, error)

Marshal returns the encoded bytes of cal.

func NewEncoder added in v0.3.3

func NewEncoder(w io.Writer) *encode.Encoder

NewEncoder returns a new encode.Encoder that writes to w.

Types

type Calendar

type Calendar parse.Calendar

Calendar is a parsed iCalendar.

func Parse

func Parse(r io.Reader, opts ...Option) (Calendar, error)

Parse parses the iCalendar from r.

Example
package main

import (
	"fmt"
	"os"

	"github.com/bounoable/ical"
)

func main() {
	f, err := os.Open("/path/to/calendar.ics")
	if err != nil {
		panic(err)
	}
	defer f.Close()

	cal, err := ical.Parse(f)
	if err != nil {
		panic(err)
	}

	// work with the events
	for _, evt := range cal.Events {
		fmt.Println(evt)
	}
}
Output:

Example (ExplicitTimeLocation)
package main

import (
	"fmt"
	"os"
	"time"

	"github.com/bounoable/ical"
	"github.com/bounoable/ical/parse"
)

func main() {
	f, err := os.Open("/path/to/calendar.ics")
	if err != nil {
		panic(err)
	}
	defer f.Close()

	loc, err := time.LoadLocation("America/Los_Angeles")
	if err != nil {
		panic(err)
	}

	cal, err := ical.Parse(f, ical.ParseWith(
		parse.Location(loc),
	))

	if err != nil {
		panic(err)
	}

	// work with the events
	for _, evt := range cal.Events {
		fmt.Println(evt)
	}
}
Output:

Example (WithContext)
package main

import (
	"context"
	"fmt"
	"os"

	"github.com/bounoable/ical"
)

func main() {
	f, err := os.Open("/path/to/calendar.ics")
	if err != nil {
		panic(err)
	}
	defer f.Close()

	ctx := context.TODO()
	cal, err := ical.Parse(f, ical.Context(ctx))
	if err != nil {
		panic(err)
	}

	// work with the events
	for _, evt := range cal.Events {
		fmt.Println(evt)
	}
}
Output:

Example (WithLexerOptions)
package main

import (
	"context"
	"fmt"
	"os"

	"github.com/bounoable/ical"
	"github.com/bounoable/ical/lex"
)

func main() {
	f, err := os.Open("/path/to/calendar.ics")
	if err != nil {
		panic(err)
	}
	defer f.Close()

	lexContext := context.TODO()

	cal, err := ical.Parse(f, ical.LexWith(
		lex.Context(lexContext),
		lex.StrictLineBreaks,
	))

	if err != nil {
		panic(err)
	}

	// work with the events
	for _, evt := range cal.Events {
		fmt.Println(evt)
	}
}
Output:

Example (WithParserOptions)
package main

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/bounoable/ical"
	"github.com/bounoable/ical/parse"
)

func main() {
	f, err := os.Open("/path/to/calendar.ics")
	if err != nil {
		panic(err)
	}
	defer f.Close()

	parseContext := context.TODO()

	cal, err := ical.Parse(f, ical.ParseWith(
		parse.Context(parseContext),
		parse.Location(time.Local),
	))

	if err != nil {
		panic(err)
	}

	// work with the events
	for _, evt := range cal.Events {
		fmt.Println(evt)
	}
}
Output:

func ParseFile

func ParseFile(filepath string, opts ...Option) (Calendar, error)

ParseFile parses the iCalendar from the file at filepath.

func ParseText

func ParseText(text string, opts ...Option) (Calendar, error)

ParseText parses the iCalendar from text.

type Option

type Option func(*config)

Option is a lex/parse option.

func Context

func Context(ctx context.Context) Option

Context adds a context to the lexer & parser.

func LexWith

func LexWith(opts ...lex.Option) Option

LexWith adds options to the lexer.

func ParseWith

func ParseWith(opts ...parse.Option) Option

ParseWith adds options to the parser.

Directories

Path Synopsis
internal
Package lex tokenizes iCalendar files for the parser.
Package lex tokenizes iCalendar files for the parser.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL