1

I'm wanting to use my Firebase database that has the values of a product i.e. lifespan (an integer not a date) and use it to compare the date in which the user has added the item i.e. 25/03/17, I'm not sure how to achieve this. Can somebody give me some advice. I believe it is to do with approximation, so if the liespan is equal 7 then the user should see 7 days and it would decrease each day, so basically a countdown. I've looked at NSDate documentation and the SwiftDate framework and do have a bit of knowledge on the methods I might need to use.

I have this example where it gets the engagement date and compares it with the wedding date, I'm thinking this is somewhat similar to what I want to try and achieve. However as this uses two dates and I want to use a date and an integer:

    formatter.dateFormat = "dd/MM/yyyy"

    let dateArray = message["message"] as! NSMutableArray

    if let startTimeString = dateArray[0] as? String {
        let weddingDate = formatter.dateFromString(startTimeString)
        var engagementDate:NSDate? = nil

        if let endTimeString = dateArray[1] as? String {
            engagementDate = formatter.dateFromString(endTimeString)
        }
        let now = NSDate()
        let totalEngagementTime = userCalender.components(.Day, fromDate: engagementDate!, toDate: weddingDate!, options: []).day
        let daysFromEngagementUntilNow = userCalender.components(.Day, fromDate: engagementDate!, toDate: now, options: []).day
        let percentage = (Double(daysFromEngagementUntilNow) / Double(totalEngagementTime)) * 100.00
        let timeUntilWedding = userCalender.components(requestedComponent, fromDate: now, toDate: weddingDate!, options: [])

Hope I made sense, thank you in advance! :)

Chace
  • 561
  • 10
  • 28
  • Just to be sure, in your database you have both a lifespan value (integer) and the date the item was added (date), correct? If yes, all you need to do is take the current date and find the difference in dates to see how many days has passed since the item was added. You'd probably stop doing the countdown once you hit the lifespan value. I can provide code for you if that would make it easier but this should help - http://stackoverflow.com/questions/31132159/days-between-2-nsdates-in-a-calendar-year-swift – Fahim Mar 26 '17 at 02:00
  • Do you want it to count down each day? – Jay Mar 26 '17 at 13:19
  • @Fahim, Yes you're right the countdown would stop as soon as it reaches its lifespan. I know this can be applied to any database but are you able to demonstrate me the method using Firebase? So currently I can send the date in which I purchased an item to the databse. However I just realised that the user is providing this data so it won't work. I've been trying to get it to let only the data in the table to be selected by the user. If that makes any sense. – Chace Mar 26 '17 at 21:03
  • @Chace I'm afraid that the last bit does not make any sense to me at all :) But you might have a totally different implementation in mind than me. From where I sit, if the data is in the table, you should be able to fetch it and if you can fetch the data, you can do the calculation and display the result. But since I don't know what you have in mind, I might be totally wrong :) – Fahim Mar 27 '17 at 00:10
  • @Fahim Basically at the moment I can create an event and give it a date value. But I realised this is the wrong method. What I should do is like you mentioned, which is to fetch the data and do the calculation based on the date in which the user has set. I'm quite new to Firebase so at the moment I can only get the snapshot of the data that the user adds and display it onto a tableView. But right now I need to display the table of data that has the lifespan. – Chace Mar 27 '17 at 00:14
  • Not sure that I see the problem, but might be that I don't understand your table structure :) If the snapshot you fetch has the date and the lifespan, then you can make the calculation using those since you don't need to write anything back to Firebase. If the snapshot has data that for some reason has to be used to create the date and lifespan then you need to store it back in Firebase, then that would still work almost the same except for the part where you have to write the data back to Firebase. Perhaps provide more information in your question? – Fahim Mar 27 '17 at 00:54
  • Ok, sure. I basically would like like to create a reminder application. The user needs to be able to query the data from Firebase which I have created using a JSON file. This database will obtain the name of events and their lifespan. The user then would select a date in which they added that data and use it to compare it with the lifespan. That is how the countdown will work. Sorry if I'm not making much sense :( – Chace Mar 27 '17 at 01:23
  • @Jay I can see you have a lot of experience with Firebase as well. Would you have any suggestions on the method I could use :)? – Chace Mar 27 '17 at 01:27
  • The question is still very unclear to me. If this is a reminder app, there needs to be some kind of logic to actually get/send the reminder. Firebase doesn't have an automatic task like this or server side logic to do that so your app will have to poll - once an hour maybe? - to see if there are any existing events that need attention. If you use a polling method, you can retrieve any upcoming events pretty easily. Newly added events will notify your app but it doesn't seem that's the point. You need to see all events coming up in the next 7 days for example. – Jay Mar 27 '17 at 16:56
  • @Jay Yeah. The events will have a lifespan. Therefore I believe I need to bring it down and store into an array where user can select from. The user then needs to choose a date in which they added it and the calculation will be fine based on those two data. Hope that makes sense. I've done some research and it appears I need to use a search predicate that gets the data down from Firebase. Do you have any ideas how to do that? Basically a search through the database. So the user can only select from what's inside the database and not their own. – Chace Mar 27 '17 at 17:22
  • Still pretty unclear. Are you asking how to query Firebase for data that's between two dates? – Jay Mar 27 '17 at 17:25
  • I think that's what I'm trying to say. Create a countdown on the event that the user has chosen. So at the moment I have the even which has a name and lifespan. – Chace Mar 27 '17 at 18:49
  • @Chace Firebase doesn't offer this kind of server side logic, so it can't count down anything. However, your app can poll the server at regular intervals and notify the user of upcoming events. For example. Every hour the app queries the server for any events coming up between now and 12 hours from now. If it finds some, it notifies the user of when the event will occur. Storing a simple timestamp on the server would allow you to query an events node with .startingAt(nowTime) and .endingAt(nowTime+12 hour). I can whip out some query code if you need it. – Jay Mar 28 '17 at 17:06
  • @Jay Yes, I understand now that they don't have this logic. I basically just need calculate the date in which the user has added it the event (current date) with the date in which it is due (user will decide this date). So if you could show me to create a countdown between these dates I would very much appreciate it :) I know this might seem very basic but I'm still quite new to this and not sure how to work with it. Also apologies for the confusions and thank you for your time :) – Chace Mar 28 '17 at 17:26
  • Are you asking how to calculate the time between two dates or how to query for nodes based on dates within a range in Firebase? The word *countdown* isn't applicable here so we need to know what that means. – Jay Mar 28 '17 at 17:39
  • I assume it time between two dates, then :) – Chace Mar 28 '17 at 18:06

1 Answers1

1

In response to a comment from the OP, this answers the question how to calculate

time between two dates

as well as perform a query on Firebase to retrieve events between now and a future date.

Given a Firebase structure to track events:

events
  event_0
    datestamp: "20170405"
    event_name: "A concert"
  event_1
    datestamp: "20170501"
    event_name: "Wine tasting"
  event_2
    datestamp: "20170410"
    event_name: "50th birthday"

Assuming today is 20170402 (April 2nd, 2017) and we want all of the events for the next 30 days along with how many days until the event, when we run the following code and query:

    let minuteInterval:TimeInterval = 60.0 //how to work with TimeIntervals
    let hourInterval:TimeInterval = 60.0 * minuteInterval
    let dayInterval:TimeInterval = 24 * hourInterval
    let sevenDaysInterval = dayInterval * 30 //30 days from now

    let today = Date() //today

    var futureDate = Date()
    futureDate.addTimeInterval(sevenDaysInterval) //future date is seven days from now

    let formatter = DateFormatter()
    formatter.dateFormat = "yyyyMMdd" //format the date to match how it's stored in Firebase
    let startString = formatter.string(from: today)
    let endString = formatter.string(from: futureDate)

    let eventsRef = self.ref.child("events")
    let myQuery = eventsRef.queryOrdered(byChild: "datestamp")
                                 .queryStarting(atValue: startString)
                                 .queryEnding(atValue: endString)
    myQuery.observeSingleEvent(of: .value, with: { snapshot in
        for child in snapshot.children {
            let snap = child as! FIRDataSnapshot
            let dict = snap.value as! [String: Any]
            let eventName = dict["event_name"] as! String
            let eventDateStampString = dict["datestamp"] as! String
            let endDate = formatter.date(from: eventDateStampString)
            let daysUntilEvent = self.daysDiff(startDate: today, endDate: endDate!)

            print("event: \(eventName)  days from now: \(daysUntilEvent)")
        }
    })

and a little function do to the difference in dates calculation

func daysDiff(startDate: Date, endDate: Date) -> Int {
    let calendar = Calendar.current

    let date1 = calendar.startOfDay(for: startDate)
    let date2 = calendar.startOfDay(for: endDate)

    let a = calendar.dateComponents([.day], from: date1, to: date2)
    return a.value(for: .day)!
}

and the result is

event: A concert  days from now: 3
event: 50th birthday  days from now: 8
event: Wine tasting  days from now: 29
Jay
  • 34,438
  • 18
  • 52
  • 81
  • I'm sorry for the delay in response. I actually want to display how many days left till the event not the events until a date. Sorry if this is confusing. It is literally just a countdown where the chosen date is compared with current date. So it should display something like "5 days to go". – Chace Apr 01 '17 at 23:31
  • @Chace Super easy. I updated my answer and added a function to do that calculation. I also iterate over the snapshot to output the events in the next 30 days and the number of days until each event. You need to have some limit to how far out you are retrieving events so I used 30 days in this example, but you can easily change that. – Jay Apr 02 '17 at 12:48
  • Thank you very much. Sorry to ask and this might sound stupid but do I call this in the viewDidLoad? Because that's what I did and nothing is printing out :/ It might also have something to do with my eventRef as mine needs to get through to the usersList via user ID so it looks something like this: let eventRef = FIRDatabase.database().reference(withPath: "users/\(user.uid)/usersList"). Also, can you explain why is the limit on retrieving events necessary? – Chace Apr 02 '17 at 23:07
  • @Chace There is no limit on retrieving events - I included that code to demonstrate how it could be done - say if it's a calendar app and the user only wants to see the events in the next 30 days. Or perhaps a To Do list where the user only wants to see what needs to be done this week. As far as your code not working, that could be due to a number of things but if you create a new app (which is what I did), put the structure I included into Firebase and run the code it works (as shown by the output). You may want to craft another question to get assistance with returning data from Firebase. – Jay Apr 03 '17 at 17:14
  • Please see my update. I've got this function that gets my Firebase data so I can display both the name and the date on a tableView. So can I use your function or something similar to just get the differences in date and current date? Could you update your answer so it works with mine please :) – Chace Apr 03 '17 at 17:19
  • @Chace you should probably not change your original question too much as it invalidates the answer. Instead open a NEW question if it's different than the initial question. The function of my function was to calculate the number of days between two dates - is there something preventing you from using the code in my answer? – Jay Apr 03 '17 at 17:26
  • Ok sorry, still new to Stackoverflow. It is not printing anything. The child appears to be empty therefore the for loop is not happening. Something is not right on the myQuery. On the new project I used to test your code I only get this in the console log "Using an unspecified index. Consider adding ".indexOn": "datestamp" at /events to your security rules for better performance". – Chace Apr 03 '17 at 17:49
  • @Chace You should post a new question with a snippet of your firebase structure, your code and what the issue is. Obviously something is being overlooked but without that information, not much else we can do. I have a new product and copy and pasted the data in my answer and it's working fine. – Jay Apr 03 '17 at 18:18
  • Please have a look here: http://stackoverflow.com/questions/43191384/date-difference-with-swift-3-and-firebase – Chace Apr 03 '17 at 18:33