Search code examples
swiftdatefor-looprealm

How do you add weekly, monthly, and yearly intervals to a date in a loop?


I am appending items to an array with a for loop to add to Realm.

var transactionArray:[Transaction] = []

for _ in 1...numberOfTransactionsToAdd {

            let addedTransaction = Transaction()
            
            addedTransaction.transactionAmount = amount
            addedTransaction.transactionName = name
            addedTransaction.transactionDescription = desc
            addedTransaction.transactionDate = datePicked
            addedTransaction.transactionCategory = category

            transactionArray.append(addedTransaction)
        }

let transactionList = List<Transaction>()
        
        
        for transaction in transactionArray {
            
            transactionList.append(transaction)
            
        }
        
        try! realm.write {
            realm.add(transactionList)
        }

This code works perfectly, but it saves all of the transactions on the same date.

I need to make them recurring transactions by adding weekly and monthly time intervals to the date.

I've tried creating a nested for loop to add date components:

for _ in 0...1 {
                datePicked = Calendar.current.date(byAdding: timeComponent, to: datePicked)!
            }

And I've tried adding time for weeks, but this will not work for months:

for _ in 0...7 {
                datePicked = datePicked + 24*60*60
            }

How do I append these addedTransaction objects with weekly and monthly intervals?


Solution

  • There is an existing answer but it relies on a third party module, which isn't a bad thing but if it were to not be updated in the future, it would invalidate the answer. Additionally, the objects in use are not clearly defined.

    TL;DR - there's no need for a list or an array. Write the transactions as they are created and populated.

    Detail:

    So here's a more complete Swift answer, starting with the TransactionClass Realm object that has a convenience init for the date of the transaction as well as a primary key which is generally a good idea to have on objects.

    class TransactionClass: Object {
        @objc dynamic var transaction_id = UUID().uuidString
        @objc dynamic var date_picked = Date()
        convenience init(theDate: Date) {
            self.init()
            self.date_picked = theDate
        }
        override static func primaryKey() -> String? {
            return "transaction_id"
        }
    }
    

    Then a function that creates a number of recurring transactions based on the pickedDate

    let datePicked = Date() //using today as an example, insert your date here
    let numMonths = 12 //recurring for 12 months
    var dateComponent = DateComponents()
    
    for index in 0..<numMonths {
        dateComponent.month = index
        if let futureDate = Calendar.current.date(byAdding: dateComponent, to: datePicked) {
            let t = TransactionClass(theDate: futureDate)
            try! realm.write {
                realm.add(t)
            }
        }
    }
    

    and the output when printed

    2020-07-12 13:30:32 +0000
    2020-08-12 13:30:32 +0000
    2020-09-12 13:30:32 +0000
    2020-10-12 13:30:32 +0000
    2020-11-12 14:30:32 +0000
    2020-12-12 14:30:32 +0000
    2021-01-12 14:30:32 +0000
    2021-02-12 14:30:32 +0000
    2021-03-12 14:30:32 +0000
    2021-04-12 13:30:32 +0000
    2021-05-12 13:30:32 +0000
    2021-06-12 13:30:32 +0000