Determine Date Range Based on Today's Date

I think I need some help from folks brighter than me to solve this one.

I have the following rule which does two things:

  1. Calculates current home energy cost based on a kWh reading from a SmartThings device.
  2. Calculates an estimated final bill cost for the current billing period.

Currently the final bill cost is determined using two manually updated date variables so I can calculate the total number of days and the number of days so far in the cycle. That all works great. But what I’d like to do is somehow automate this so I don’t have to remember to set the date variables each cycle.

I have a chart from my TDSP that shows every date I can expect my billing period to end each month. There must be some way I can store that info in an array and then perform a comparison in a rule to determine where we are date-wise and pull the right dates from the array. Does that makes sense? I’ll keep thinking this through but any suggestions would be very welcome.

TIA

I’m not sure I fully understand the complete picture, but here’s some ideas around filtering dates…

dates = ['2023-05-26', '2023-06-30', '2023-07-28']
today = now()

filteredDates = filter(dates, today < date(x, 'YYYY-MM-DD'))
filteredDates[0]

Here’s what’s happening line by line:

  1. We initialize a dates array with the values we are interested in.
    • You could also store these JSON encoded in a text variable and decode them for use in your expression:
      dates = jsonDecode($myDates) 
      
  2. Store a reference to today so it’s static
    • You could just use now() directly in each iteration, but if the expression was running right on the edge of a day, in theory it could cause some funkiness, so we make sure we have a static reference
  3. Use an expression to filter to only the dates we have remaining (eg. filter out past dates)
  4. Grab the first date in the filtered array of dates
    • This assumes that the dates are in order, so the first item would be the next date we are interested in

Okay, I follow that. Let me put some more thought around this but I think that will help me get to what I want.

For more context, I simply want to determine what two dates in the array I am between based on today.

Thanks Josh.

That’s functionally what happens with my example above assuming the dates in the array are in order.

It filters out any dates that have already passed, leaving only dates that are in the future. So the first date should be the immediate next date.

Depending on your needs, there may of course be a situation where none of the dates are valid anymore as you haven’t updated the array in a while… in which case you might want to add whatever fallback logic is reasonable.

Overly complex before/after approach

You could do a complex expression that gets the indexes of the array items and iterates through those so you can do some math to do some before/after type checks, but the expression starts to get really ugly in that case.

And it ends up being the same result as the much simpler expression shown above.

dates = ['2023-05-26', '2023-06-30', '2023-07-28']
today = now()
dateFormat = "YYYY-MM-DD"

indexes = objectKeys(dates)
filteredIndexes = filter(indexes, date(dates[number(max(x - 1, 0))], dateFormat) < today < date(dates[number(x)], dateFormat))

dates[number(filteredIndexes[0])]

In fact, this even introduces its own issues that the first comparison in the filter() function has to be capped with a minimum index… and at that point the comparison isn’t valid since you can’t be both after and before the first date… which means you have to either inject a dummy date in the past as the first item in the array or add even more logic to the expression to handle that edge case.

That’s where the simpler filtering approach I originally mentioned works better as long as your dates are in order.

1 Like

Thanks for taking the time to add the additional explanation and ideas Josh. I’m confident I have what I need now.

1 Like

In order to the grab the date in the array prior to the current date I am taking off 35 days (in milliseconds). Is there a more elegant way of doing that?

dates = ['2023-01-17', '2023-02-15', '2023-03-17', '2023-04-18', '2023-05-17', '2023-06-16', '2023-07-18', '2023-08-16', '2023-09-15', '2023-10-17', '2023-11-15', '2023-12-15']
today = now()
filteredDates = filter(dates, today - 3024000000 < date(x, 'YYYY-MM-DD'))
filteredDates[0]