Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Catalan support #16

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion Sources/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ private func baseOption(strictMode: Bool) -> ModeOptio {
ZHDeadlineFormatParser(strictMode: strictMode),
ZHTimeExpressionParser(strictMode: strictMode),
ZHWeekdayParser(strictMode: strictMode),

// CA
CATimeAgoFormatParser(strictMode: strictMode),
CADeadlineFormatParser(strictMode: strictMode),
CATimeExpressionParser(strictMode: strictMode),
CAMonthNameLittleEndianParser(strictMode: strictMode),
CASlashDateFormatParser(strictMode: strictMode),

], refiners: [
// Removing overlaping first
Expand Down Expand Up @@ -116,12 +123,16 @@ public func casualModeOption() -> ModeOptio {
DECasualDateParser(strictMode: false),
DEWeekdayParser(strictMode: false),
DEMorgenTimeParser(strictMode: false),

// CA
CACasualDateParser(strictMode: false),
CAWeekdayParser(strictMode: false),

], at: 0)

return options
}

public enum Language {
case english, spanish, french, japanese, german, chinese
case english, spanish, catalan, french, japanese, german, chinese
}
116 changes: 116 additions & 0 deletions Sources/Parsers/CA/CACasualDateParser.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//
// CACasualDateParser.swift
// SwiftyChrono
//
// Translated from ESCasualDateParser.swift.
// Original work Copyright © 2017 Potix. All rights reserved.
//

import Foundation

/*
Valid patterns:
- aquest matí -> today in the morning
- aquesta tarda -> today in the afternoon/evening
- aquesta nit -> tonight
- ahir pel matí -> yesterday in the morning
- ahir per la tarda -> yesterday in the afternoon/evening
- ahir per la nit -> yesterday at night
- demà pel matí -> tomorrow in the morning
- demà per la tarda -> tomorrow in the afternoon/evening
- demà per la nit -> tomorrow at night
- ahir a la nit -> tomorrow at night
- avui -> today
- ahir -> yesterday
- demà -> tomorrow
*/
private let PATTERN = "(\\W|^)(ara|aquesta?\\s*(matí|tarda|nit)|(ahir|demà)\\s*(per\\s*la|pel)\\s*(matí|tarda|nit)|avui|demà|ahir\\s+(a|per)\\s+la\\s+nit|ahir)(?=\\W|$)"

public class CACasualDateParser: Parser {
override var pattern: String { return PATTERN }
override var language: Language { return .catalan }

override public func extract(text: String, ref: Date, match: NSTextCheckingResult, opt: [OptionType: Int]) -> ParsedResult? {
let (matchText, index) = matchTextAndIndex(from: text, andMatchResult: match)
var result = ParsedResult(ref: ref, index: index, text: matchText)

let refMoment = ref
var startMoment = refMoment
let regex = try! NSRegularExpression(pattern: "\\s+")
let lowerText = regex.stringByReplacingMatches(in: matchText.lowercased(), range: NSRange(location: 0, length: matchText.count), withTemplate: " ")

if lowerText == "demà" {
// Check not "Tomorrow" on late night
if ref.hour > 1 {
startMoment = startMoment.added(1, .day)
}

} else if lowerText == "ahir" {

startMoment = startMoment.added(-1, .day)

} else if NSRegularExpression.isMatch(forPattern: "ahir\\s+a\\s+la\\s+nit", in: lowerText) {
result.start.imply(.hour, to: 0)
if refMoment.hour > 6 {
startMoment = startMoment.added(-1, .day)
}

} else if NSRegularExpression.isMatch(forPattern: "aquest", in: lowerText) {

let secondMatch = match.string(from: text, atRangeIndex: 3).lowercased()
if secondMatch == "tarda" {
result.start.imply(.hour, to: 18)

} else if secondMatch == "matí" {
result.start.imply(.hour, to: 6)

} else if (secondMatch == "nit") {

// Normally means this coming midnight
result.start.imply(.hour, to: 22)
result.start.imply(.meridiem, to: 1)

}

} else if NSRegularExpression.isMatch(forPattern: "(?:per\\s*la|pel)", in: lowerText) {
let firstMatch = match.string(from: text, atRangeIndex: 4).lowercased()
if firstMatch == "ahir" {
startMoment = startMoment.added(-1, .day)

} else if firstMatch == "demà" {
startMoment = startMoment.added(1, .day)

}


let secondMatch = match.string(from: text, atRangeIndex: 5).lowercased()
if secondMatch == "tarda" {
result.start.imply(.hour, to: 18)

} else if secondMatch == "demà" {
result.start.imply(.hour, to: 9)

} else if secondMatch == "nit" {

// Normally means this coming midnight
result.start.imply(.hour, to: 22)
result.start.imply(.meridiem, to: 1)

}

} else if NSRegularExpression.isMatch(forPattern: "ara", in: lowerText) {

result.start.imply(.hour, to: refMoment.hour)
result.start.imply(.minute, to: refMoment.minute)
result.start.imply(.second, to: refMoment.second)
result.start.imply(.millisecond, to: refMoment.millisecond)

}

result.start.assign(.day, value: startMoment.day)
result.start.assign(.month, value: startMoment.month)
result.start.assign(.year, value: startMoment.year)
result.tags[.caCasualDateParser] = true
return result
}
}
65 changes: 65 additions & 0 deletions Sources/Parsers/CA/CADeadlineFormatParser.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// CADeadlineFormatParser.swift
// SwiftyChrono
//
// Translated from ESDeadlineFormatParser.swift.
// Original work Copyright © 2017 Potix. All rights reserved.
//

import Foundation

private let PATTERN = "(\\W|^)(d'aquí|dins\\s*de|dintre\\s*de|dins\\s*d'|dintre\\s*d'|en)\\s*([0-9]+|mig|mitja|una?)\\s*(minuts?|hores|hora|dies|dia)\\s*(?=(?:\\W|$))"



public class CADeadlineFormatParser: Parser {
override var pattern: String { return PATTERN }
override var language: Language { return .catalan }

override public func extract(text: String, ref: Date, match: NSTextCheckingResult, opt: [OptionType: Int]) -> ParsedResult? {
let (matchText, index) = matchTextAndIndex(from: text, andMatchResult: match)
var result = ParsedResult(ref: ref, index: index, text: matchText)
result.tags[.caDeadlineFormatParser] = true

let number: Int
let numberText = match.string(from: text, atRangeIndex: 3).lowercased()
let parsedNumber = Int(numberText)

if parsedNumber == nil {
if NSRegularExpression.isMatch(forPattern: "mig|mitja", in: numberText) {
number = HALF
} else {
number = 1
}
} else {
number = parsedNumber!
}

let number4 = match.string(from: text, atRangeIndex: 4).lowercased()
var date = ref
if NSRegularExpression.isMatch(forPattern: "dia|dies", in: number4) {
date = number != HALF ? date.added(number, .day) : date.added(12, .hour)

result.start.assign(.year, value: date.year)
result.start.assign(.month, value: date.month)
result.start.assign(.day, value: date.day)
return result;
}


if NSRegularExpression.isMatch(forPattern: "hor", in: number4) {
date = number != HALF ? date.added(number, .hour) : date.added(30, .minute)
} else if NSRegularExpression.isMatch(forPattern: "minut", in: number4) {
date = number != HALF ? date.added(number, .minute) : date.added(30, .second)
}

result.start.imply(.year, to: date.year)
result.start.imply(.month, to: date.month)
result.start.imply(.day, to: date.day)
result.start.assign(.hour, value: date.hour)
result.start.assign(.minute, value: date.minute)

return result
}
}

92 changes: 92 additions & 0 deletions Sources/Parsers/CA/CAMonthNameLittleEndianParser.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//
// CAMonthNameLittleEndianParser.swift
// SwiftyChrono
//
// Translated from ESMonthNameLittleEndianParser.swift.
// Original work Copyright © 2017 Potix. All rights reserved.
//

import Foundation

private let PATTERN = "(\\W|^)" +
"(?:(Diumenge|Dilluns|Dimarts|Dimecres|Dijous|Divendres|Dissabte|Dg|Dl|Dt|Dc|Dj|Dv|Ds)\\s*,?\\s*)?" +
"([0-9]{1,2})(?:r|n|t|è)?" +
"(?:\\s*(?:des|de|del|\\-|\\–|al?|fins|\\s)\\s*([0-9]{1,2})(?:r|n|t|è)?)?\\s*(?:de|d')?\\s*" +
"(Gen(?:er|\\.)?|Feb(?:rer|\\.)?|Mar(?:ç|\\.)?|Abr(?:il|\\.)?|Mai(?:g|\\.)?|Jun(?:y|\\.)?|Jul(?:iol|\\.)?|Ago(?:st|\\.)?|Set(?:embre|\\.)?|Oct(?:ubre|\\.)?|Nov(?:embre|\\.)?|Des(?:embre|\\.)?)" +
"(?:\\s*(?:del?|de)?(\\s*[0-9]{1,4}(?![^\\s]\\d))(\\s*[ad]\\.?\\s*c\\.?|a\\.?\\s*d\\.?)?)?" +
"(?=\\W|$)"

private let weekdayGroup = 2
private let dateGroup = 3
private let dateToGroup = 4
private let monthNameGroup = 5
private let yearGroup = 6
private let yearBeGroup = 7

public class CAMonthNameLittleEndianParser: Parser {
override var pattern: String { return PATTERN }
override var language: Language { return .catalan }

override public func extract(text: String, ref: Date, match: NSTextCheckingResult, opt: [OptionType: Int]) -> ParsedResult? {
let (matchText, index) = matchTextAndIndex(from: text, andMatchResult: match)
var result = ParsedResult(ref: ref, index: index, text: matchText)

let month = CA_MONTH_OFFSET[match.string(from: text, atRangeIndex: monthNameGroup).lowercased()]!

let day = Int(match.string(from: text, atRangeIndex: dateGroup))!

if match.isNotEmpty(atRangeIndex: yearGroup) {
var year = Int(match.string(from: text, atRangeIndex: yearGroup).trimmed())!

if match.isNotEmpty(atRangeIndex: yearBeGroup) {
let yearBe = match.string(from: text, atRangeIndex: yearBeGroup)
if NSRegularExpression.isMatch(forPattern: "a\\.?\\s*c\\.?", in: yearBe) {
// antes de Cristo
year = -year
}
} else if year < 100 {

year = year + 2000;
}

result.start.assign(.day, value: day)
result.start.assign(.month, value: month)
result.start.assign(.year, value: year)
} else {
//Find the most appropriated year
var refMoment = ref
refMoment = refMoment.setOrAdded(month, .month)
refMoment = refMoment.setOrAdded(day, .day)
refMoment = refMoment.setOrAdded(ref.year, .year)

let nextYear = refMoment.added(1, .year)
let lastYear = refMoment.added(-1, .year)
if abs(nextYear.differenceOfTimeInterval(to: ref)) < abs(refMoment.differenceOfTimeInterval(to: ref)) {
refMoment = nextYear
} else if abs(lastYear.differenceOfTimeInterval(to: ref)) < abs(refMoment.differenceOfTimeInterval(to: ref)) {
refMoment = lastYear
}

result.start.assign(.day, value: day)
result.start.assign(.month, value: month)
result.start.imply(.year, to: refMoment.year)
}

// Weekday component
if match.isNotEmpty(atRangeIndex: weekdayGroup) {
let weekday = CA_WEEKDAY_OFFSET[match.string(from: text, atRangeIndex: weekdayGroup).lowercased()]
result.start.assign(.weekday, value: weekday)
}

// Text can be 'range' value. Such as '12 - 13 January 2012'
if match.isNotEmpty(atRangeIndex: dateToGroup) {
result.end = result.start.clone()
result.end?.assign(.day, value: Int(match.string(from: text, atRangeIndex: dateToGroup))!)
}

result.tags[.caMonthNameLittleEndianParser] = true
return result
}
}


Loading