Help us understand the problem. What is going on with this article?

Get observed public holidays list from Google API

More than 1 year has passed since last update.

There is a useful Google API available to developers who register with the Google Console and obtain an API key. For a chosen country, this API returns a list of dates which are public holidays.

However, there are problems with the default output, e.g

  • a single public holiday may in some cases have an original date and an observed (if, for example, the original date is not possible e.g. is on a weekend). The API returns both dates as separate items.
  • multiple holidays can are given with different dates but identical names
  • a single public holiday date can be duplicated, with some instances including an extra "holiday" suffix in their name
  • holidays with identical names but from multiple years (both previous, current and future years) are given

The method for extracting a list of OBSERVED public holidays in Japan, in Japanese language is presented here for iOS/Swift

URL

https://www.googleapis.com/calendar/v3/calendars/{LANGUAGE}.{COUNTRY}%23holiday%40group.v.calendar.google.com/events?key={API_KEY}

where

  • {LANGUAGE} is the requested language, e.g: ja, en
  • {COUNTRY} is the requested country, e.g: japanese, uk, french
  • {API_KEY} is the API key from your developer account

Define a custom date handler object

This object helps to compare dates extracted from the API

struct PublicHoliday{

    // some holiday names are provided with an "observed" suffix - so we define a base name (without this suffix) to more easily compare dates 
    let baseName: String
    let name: String
    let start: String
    let end: String

    let observedKeyword: String = "observed"

    // let dates with the "observed" keyword take priority (override) for a specific holiday date
    var isOverride: Bool {
        get {
            return self.name.contains(observedKeyword)
        }
    }


    init(name: String, start: String, end: String) {
        self.name = name
        self.start = start
        self.end = end

        let components = name.split(separator: " ")
        if let last = components.last, last == observedKeyword {
            self.baseName = components.dropLast().joined(separator: " ")
        }
        else {
            self.baseName = name
        }
    }

    init(date: String) {
        self.init(name: "", start: date, end: date)
    }
}

Parse Response in Swift

The following parse function extracts only observed public holidays for the current as an array of Public Holiday objects

class GoogleCalendarAPIParser {


    static func process(json: [String: Any]) -> [PublicHoliday] {

        guard let items = json["items"] as? JSONArray,
            0 < items.count else {
            return []
        }

        // extract all dates
        var dates: [PublicHoliday] = items.compactMap { item in

            guard
                let name= item["summary"] as? String,
                let start = item["start"] as? [String: Any],
                let end = item["start"] as? [String: Any],
                let startDate = start["date"] as? String,
                let endDate = end["date"] as? String
            else {
                Swift.print("unable to parse dates", item)
                return nil
            }

            return PublicHoliday(
                name: name,
                start: startDate,
                end: endDate
            )
        }


        // keep only dates from the current year
        let currentYear = String(Calendar.current.component(.year, from: Date()))
        dates = dates.filter { $0.startDate.split("-")[0] == currentYear }

        // keep dates that are overrides (the "observed" date) and dates which are not overriden by other dates
        dates = dates.filter { date in
            let isOverride = date.isOverride
            let hasNoOverride = dates.filter {
                $0.baseName == date.baseName && $0.isOverride
                }.isEmpty
            return isOverride || hasNoOverride
        }
        return dates
    } 
}
cayozin
iOS/Android development (Swift/C++/Java/Kotlin/XML/Javascript), backend (php/mySQL) and Machine Learning (Python/Scala)
ayudante
いつもユーザー中心で技術者とコンサルタントがとことん考え抜く それがアユダンテです
https://ayudante.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした