I'm currently developing my own iOS application that makes a phone call from the press of a button. I'd like to make it so the button calls a different number depending on the time of day. My idea is to differentiate the numbers by UTC, since local time will depend on where the device is. For example, if it is between 00:01 and 08:00, then call 1234567. If it is between 08:01 and 16:00 UTC, then call 7654321.
Here is what I have so far:
import UIKit
var str = "Hello, playground"
typealias WorkingTime = (start: NSDate, end: NSDate)
typealias TelephoneNumber = String
enum Regions {
case Americas
case EMEA
case APAC
func serviceDeskNumberForRegion(region: Regions) -> TelephoneNumber {
switch self {
case .Americas:
return "00112341234"
case .EMEA:
return "12345678976543"
case .APAC:
return "3245678908"
}
}
}
//this is to create the dates from string
let dateformatter = NSDateFormatter()
dateformatter.dateFormat = "HH:mm"
//we're hardcoding....
struct WorkingTimesForRegion {
static let AmericanWorkingTimes = (start: dateformatter.dateFromString("00:01")!, end: dateformatter.dateFromString("08:00")!)
static let EMEAWorkingTimes = (start: dateformatter.dateFromString("08:01")!, end: dateformatter.dateFromString("16:00")!)
static let APACWorkingTimes = (start: dateformatter.dateFromString("16:01")!, end: dateformatter.dateFromString("00:00")!)
static func regionForTime(time: NSDate) -> Regions {
//
//here I should use the nscalendar to make sure all times are represented on the same timezones, like UTC. Not sure how to go about this.
//
//here I probably need to check both end and start
//a switch case would've been more elegant here but I don't see how to build it at the moment
//an option I would explore is using NSRange as they make sense in principle and can be used in switch statements.
//but I don't know if you can create ranges of dates ...
if time.compare(WorkingTimesForRegion.AmericanWorkingTimes.end) == .OrderedAscending {
return .Americas
} else if time.compare(WorkingTimesForRegion.EMEAWorkingTimes.end) == .OrderedAscending {
return .EMEA
} else if time.compare(WorkingTimesForRegion.EMEAWorkingTimes.end) == .OrderedAscending {
return .APAC
}
//just in case
return .EMEA
}
}
func serviceDeskForTime(time: NSDate) -> TelephoneNumber {
let serviceDeskInCharge = WorkingTimesForRegion.regionForTime(time)
return serviceDeskInCharge.serviceDeskNumberForRegion(serviceDeskInCharge)
}
//see if it works
serviceDeskForTime(dateformatter.dateFromString("05:00")!)
func call() -> Bool {
guard let url = NSURL(string: "tel://123456765") else { return false }
if UIApplication.sharedApplication().canOpenURL(url) {
return UIApplication.sharedApplication().openURL(url)
}
return false
}
Any help would be appreciated. Thank you!
Given this function:
func isLessThanDate(dateToCompare: NSDate) -> Bool {
var isLess = false
print(self)
print(dateToCompare)
if self.compare(dateToCompare) == NSComparisonResult.OrderedAscending {
isLess = true
}
return isLess
}
I get OrderedAscending with the same date.
If you want to ignore the millisecond differences, you can use floor on the two dates, but without knowing the exact intent of your code, I'm not sure if that's really what you want. See the comments on this answer for an alternative using NSCalendar functions.
BTW, you can simplify your function if you directly return a boolean value instead of using the isLess variable:
func isLessThanDate(dateToCompare: NSDate) -> Bool {
return self.compare(dateToCompare) == NSComparisonResult.OrderedAscending
}
I have to filter a list depending on the start date and end date. The NSDate extension is as follows,
public func <(a: NSDate, b: NSDate) -> Bool {
return a.compare(b) == NSComparisonResult.OrderedAscending
}
public func ==(a: NSDate, b: NSDate) -> Bool {
return a.compare(b) == NSComparisonResult.OrderedSame
}
extension NSDate:Comparable{}
the list is as follows,
class Observation
{
var date:NSDate = NSDate()
var value:String = ""
}
var observationList = [Observation]()
now i am filtering like this,
let filterObservations = observationList.filter( { return $0.date >= startDate && $0.date < endDate} )
but it is not returning anything. Can anyone please point me what i did wrong. my observationList has definitely got an item lying in start date and end date range.
Thanks,
neena
How can we compare two strings in swift ignoring case ?
for eg :
var a = "Cash"
var b = "cash"
Is there any method that will return true if we compare var a & var b
Try this :
For older swift:
var a : String = "Cash"
var b : String = "cash"
if(a.caseInsensitiveCompare(b) == NSComparisonResult.OrderedSame){
println("Et voila")
}
Swift 3+
var a : String = "Cash"
var b : String = "cash"
if(a.caseInsensitiveCompare(b) == .orderedSame){
print("Et voila")
}
Use caseInsensitiveCompare method:
let a = "Cash"
let b = "cash"
let c = a.caseInsensitiveCompare(b) == .orderedSame
print(c) // "true"
ComparisonResult tells you which word comes earlier than the other in lexicographic order (i.e. which one comes closer to the front of a dictionary). .orderedSame means the strings would end up in the same spot in the dictionary
if a.lowercaseString == b.lowercaseString {
//Strings match
}
Try this:
var a = "Cash"
var b = "cash"
let result: NSComparisonResult = a.compare(b, options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil, locale: nil)
// You can also ignore last two parameters(thanks 0x7fffffff)
//let result: NSComparisonResult = a.compare(b, options: NSStringCompareOptions.CaseInsensitiveSearch)
result is type of NSComparisonResult enum:
enum NSComparisonResult : Int {
case OrderedAscending
case OrderedSame
case OrderedDescending
}
So you can use if statement:
if result == .OrderedSame {
println("equal")
} else {
println("not equal")
}
localizedCaseInsensitiveContains : Returns whether the receiver contains a given string by performing a case-insensitive, locale-aware search
if a.localizedCaseInsensitiveContains(b) {
//returns true if a contains b (case insensitive)
}
Edited:
caseInsensitiveCompare : Returns the result of invoking compare(_:options:) with NSCaseInsensitiveSearch as the only option.
if a.caseInsensitiveCompare(b) == .orderedSame {
//returns true if a equals b (case insensitive)
}
CORRECT WAY:
let a: String = "Cash"
let b: String = "cash"
if a.caseInsensitiveCompare(b) == .orderedSame {
//Strings match
}
Please note: ComparisonResult.orderedSame can also be written as .orderedSame in shorthand.
OTHER WAYS:
a.
if a.lowercased() == b.lowercased() {
//Strings match
}
b.
if a.uppercased() == b.uppercased() {
//Strings match
}
c.
if a.capitalized() == b.capitalized() {
//Strings match
}
Could just roll your own:
func equalIgnoringCase(a:String, b:String) -> Bool {
return a.lowercaseString == b.lowercaseString
}
For Swift 5
Ignoring the case and compare two string
var a = "cash"
var b = "Cash"
if(a.caseInsensitiveCompare(b) == .orderedSame){
print("Ok")
}
Phone numbers comparison example; using swift 4.2
var selectPhone = [String]()
if selectPhone.index(where: {$0.caseInsensitiveCompare(contactsList[indexPath.row].phone!) == .orderedSame}) != nil {
print("Same value")
} else {
print("Not the same")
}
You can just write your String Extension for comparison in just a few line of code
extension String {
func compare(_ with : String)->Bool{
return self.caseInsensitiveCompare(with) == .orderedSame
}
}
Swift 4, I went the String extension route using caseInsensitiveCompare() as a template (but allowing the operand to be an optional). Here's the playground I used to put it together (new to Swift so feedback more than welcome).
import UIKit
extension String {
func caseInsensitiveEquals<T>(_ otherString: T?) -> Bool where T : StringProtocol {
guard let otherString = otherString else {
return false
}
return self.caseInsensitiveCompare(otherString) == ComparisonResult.orderedSame
}
}
"string 1".caseInsensitiveEquals("string 2") // false
"thingy".caseInsensitiveEquals("thingy") // true
let nilString1: String? = nil
"woohoo".caseInsensitiveEquals(nilString1) // false
Swift 3: You can define your own operator, e.g. ~=.
infix operator ~=
func ~=(lhs: String, rhs: String) -> Bool {
return lhs.caseInsensitiveCompare(rhs) == .orderedSame
}
Which you then can try in a playground
let low = "hej"
let up = "Hej"
func test() {
if low ~= up {
print("same")
} else {
print("not same")
}
}
test() // prints 'same'
You could also make all the letters uppercase (or lowercase) and see if they are the same.
var a = “Cash”
var b = “CASh”
if a.uppercaseString == b.uppercaseString{
//DO SOMETHING
}
This will make both variables as ”CASH” and thus they are equal.
You could also make a String extension
extension String{
func equalsIgnoreCase(string:String) -> Bool{
return self.uppercaseString == string.uppercaseString
}
}
if "Something ELSE".equalsIgnoreCase("something Else"){
print("TRUE")
}
Swift 3
if a.lowercased() == b.lowercased() {
}
Swift 3:
You can also use the localized case insensitive comparison between two strings function and it returns Bool
var a = "cash"
var b = "Cash"
if a.localizedCaseInsensitiveContains(b) {
print("Identical")
} else {
print("Non Identical")
}
extension String
{
func equalIgnoreCase(_ compare:String) -> Bool
{
return self.uppercased() == compare.uppercased()
}
}
sample of use
print("lala".equalIgnoreCase("LALA"))
print("l4la".equalIgnoreCase("LALA"))
print("laLa".equalIgnoreCase("LALA"))
print("LALa".equalIgnoreCase("LALA"))
I would like to filter my custom objects with a date property.
For example:
class Event
{
let dateFrom: NSDate!
let dateTo: NSDate!
init(dateFrom: NSDate, dateTo: NSDate) {
self.dateFrom = dateFrom
self.dateTo = dateTo
}
}
Now i have a List of maybe 500 Events, and i just want to show the Events for a specific date. I could loop through all Objects, and create a new Array of Objects, but could i also use a filter?
Ill tried something like this:
let specificEvents = eventList.filter( { return $0.dateFrom > date } )
Where date is a NSDate Object for a specific date, but i am not able to use the > operater.
Is there an easy way to get all the events for a specific date, where the date is between the dateFrom and dateTo period?
Thanks to Martin for pointing me into the right direction.
Here is an answer if someone else is looking how to solve this in Swift:
Add an Extension to NSDate:
public func <(a: NSDate, b: NSDate) -> Bool {
return a.compare(b) == NSComparisonResult.OrderedAscending
}
public func ==(a: NSDate, b: NSDate) -> Bool {
return a.compare(b) == NSComparisonResult.OrderedSame
}
extension NSDate: Comparable { }
So you are able to use the < and > operator for NSDate comparison.
var date = dateFormatter.dateFromString(dateString)
var dateTomorrow = date?.dateByAddingTimeInterval(NSTimeInterval(60*60*24)) // add one Day
eventsToday = allEvents.filter( { return $0.dateFrom >= date && $0.dateTo < dateTomorrow} )
For Swift 3.x update :-
extension Date: Comparable{
public static func <(a: Date, b: Date) -> Bool{
return a.compare(b) == ComparisonResult.orderedAscending
}
static public func ==(a: Date, b: Date) -> Bool {
return a.compare(b) == ComparisonResult.orderedSame
}
}