5

I am making a calendar app. I have one array of selected dates. User selected it previously and they are stored there.

var selectedDays = [NSDate]()

When app loads I have to display these dates, but everything is overcomplicated because Firebase doesn't accept NSDate

I have another array var selectedDaysForFirebase = [String]() which is the same array as above only dates are converted to strings to accomodate Firebase.

This is how I save selected dates:

// 1. Append converted date into selectedDaysForFirebase array
            let day = dateFormatter.stringFromDate(date)
            selectedDaysForFirebase.append(day)

// 2. Push data to Firebase
            ref.childByAppendingPath("dates").setValue(selectedDaysForFirebase)

My Firebase has user auth. so every user has it's own little database with dates.

In my viewDidLoad I have to grab that dates array from Firebase and store it in my selectedDates array which accepts NSDate

ref.childByAppendingPath("dates").observeEventType(.Value, withBlock: { snapshot in

        if let dates = snapshot.value as? NSArray {
             print(dates)
             // convert firebase array of dates with array of dates that only accepts NSDate
        }

        }, withCancelBlock: { error in
             print(error.description)
        })

This outputs:

(
    "2016-04-10",
    "2016-04-11",
    "2016-04-12"
)

I think there is a better way to store dates and then retreive it and I hope somebody could help me with this.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Kira
  • 1,575
  • 4
  • 26
  • 48
  • Why don't use timestamps? – Larme Apr 07 '16 at 13:01
  • Oh, I'm not too familiar how this works. How would I make a stamp from selected date which outputs NSDate? – Kira Apr 07 '16 at 13:09
  • You can use `dateWithTimeIntervalSince1970:` and `timeIntervalSinceReferenceDate` to convert `NSDate` and NSTimeInterval (`double`) (and vice-versa), and just store doubles values in FireBase. – Larme Apr 07 '16 at 13:24
  • This is the first time I see this functions. When user taps on some date on my calendar it outputs NSDate, and in that function that handles tapping on a date, I have to use `dateWithTimeIntervalSince1970` and then store it to Firebase. Can you explain a bit how this works. – Kira Apr 07 '16 at 13:37
  • The way we keep dates is just in fact the time since 1/1/1970 (in seconds). NSDate is just an object to easily handle them (since it's more readable than `1460036331` for `2016-04-07T13:38:51+00:00`). I don't use FireBase, but I imagine it can store `double`. So that may be a way to do it. – Larme Apr 07 '16 at 13:39
  • Yes, Firebase accepts numbers but wouldn't I get the same thing I'm trying to achieve now? I have to convert my Firebase array into NSDate array for displaying on a calendar so I don't know if there would be any difference between converting from timestamps to NSDate and converting strings into NSDate. I will try it somehow, I have to figure out a way to convert NSDate to Double first – Kira Apr 07 '16 at 13:43

4 Answers4

8

get a date from a double:

var interval = Double()
var date = NSDate()
date = NSDate(timeIntervalSince1970: interval)

other way around, get double from date:

interval = date.timeIntervalSince1970
Peter de Vries
  • 780
  • 1
  • 6
  • 14
  • This is better than the accepted answer. Not only is it simpler, but different strings can be produced depending on what timezone and calendar your user is fetching from. – Eric Feb 24 '22 at 22:26
8

The answer really depends on how you are using your date.

'numbers' cannot be stored in Firebase; any numeric value is first converted (by Firebase) to NSNumber for storage. See Understanding Data

You need to determine how you will be using your date and how much granularity will be needed. In some cases

2016-04-06

is enough, but other times you may need more

2016-04-06 14:00:00

I would suggest simply storing these as strings as they are sortable, easily manipulated and can be brought into a NSDate object or taken out of an NSDate object.

Here's some sample code to convert NSDate to a formatted string, similar to a time stamp, which can then be stored in Firebase as a string.

NSDateFormatter *dateFormat = [NSDateFormatter new];
[dateFormat setDateFormat: @"yyyy-MM-dd HH:mm:ss zzz"];

NSString *dateString = [dateFormat stringFromDate:[NSDate date]];

NSLog(@"%@",dateString);

and the other way from formatted string to NSDate

NSDate *d = [NSDate new];

d = [dateFormat dateFromString:dateString];

NSLog(@"the date %@", d);

The super most important thing is: keep it consistent. However you do it, do it the same way every time in your code.

Oh - one other thing. Array's. Array's should be used sparingly and only in specific use case situations in Firebase. They can be challenging to work with as you don't have access to specific indexes or have the ability to change, add or remove a single index.

Here's a much better structure

my_dates
    date_0
      date_stamp: 2016-04-06
    date_1
      date_stamp: 2016-04-07

the date keys (date_0, date_1) are generated with childByAutoId.

Jay
  • 34,438
  • 18
  • 52
  • 81
0

Since firebase is a document db, json based I strongly advice to use ISO 8601 formatted date-times. This is a format like:

2012-04-23T18:25:43.511Z

In this post you can find a good explanation why:

The "right" JSON date format

HixField
  • 3,538
  • 1
  • 28
  • 54
0

Swift 4:

Figured it out finally.

Save this to firebase

let date = DateFormatter.localizedString(from: Date(), dateStyle: .short, timeStyle: .none)

Change the dateStyle and timeStyle as you wish

save the variable date to firebase DB

Joel
  • 327
  • 4
  • 3