Try function issue

When I use the Try function, it goes to failover but when I remove it, the expression calculates correctly. Why is that? I'm probably doing something wrong. How would I fix this?

Here is the code:

try(
	if(now()>=todate(tostr(dateformat(if(todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,4] + ':00')>=todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + '00:00' + ':00') &&
										todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,4] + ':00')<todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[0,4] + ':00'),
										addDays({[.]Production Shift 1/Working Date},1), {[.]Production Shift 1/Working Date}
										), 
							'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,4] + ':00') && 
	now()<todate(tostr(dateformat(if(todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,5] + ':00')>=todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + '00:00' + ':00') &&
									todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,5] + ':00')<todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[0,4] + ':00'),
									addDays({[.]Production Shift 1/Working Date},1), {[.]Production Shift 1/Working Date}
									), 
						'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,5] + ':00') && 
	{[.]Production Shift 1/Hours/Shift Var}!=11, 
	secondsbetween(now(), todate(tostr(dateformat(if(todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,5] + ':00')>=todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + '00:00' + ':00') &&
													todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,5] + ':00')<todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[0,4] + ':00'),
													addDays({[.]Production Shift 1/Working Date},1), {[.]Production Shift 1/Working Date}
													), 
										'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,5] + ':00')
					),
			if(now()<todate(tostr(dateformat(if(todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,4] + ':00')>=todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + '00:00' + ':00') &&
												todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,4] + ':00')<todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[0,4] + ':00'),
												addDays({[.]Production Shift 1/Working Date},1), {[.]Production Shift 1/Working Date}
											 	), 
								'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,4] + ':00'), 
			secondsbetween(todate(tostr(dateformat(if(todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,4] + ':00')>=todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + '00:00' + ':00') &&
													todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,4] + ':00')<todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[0,4] + ':00'),
													addDays({[.]Production Shift 1/Working Date},1), {[.]Production Shift 1/Working Date}
													), 
										'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,4] + ':00'),
							todate(tostr(dateformat(if(todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,5] + ':00')>=todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + '00:00' + ':00') &&
													todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,5] + ':00')<todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[0,4] + ':00'),
													addDays({[.]Production Shift 1/Working Date},1), {[.]Production Shift 1/Working Date}
													), 
										'MM/dd/yyyy')) + ' ' + {[.]Production Shift 1/Hours/Breaks}[5,5] + ':00')
							),
			0)
	),
99)

Thanks,

Yuck! What are you checking?
Why are you not working with DateTime datatypes throughout?

1 Like

I'm using a dataset with time string only and need to do some conversions.

  1. Why are you using time strings? Usually we try to keep datetime as datetime datatype until the point of display.
  2. What is the source of the dataset? If it is a query then why not return datetime?

It's a memory dataset tag that users are using to setup their hours so there is no need for date.

I'm trying to understand the issue I'm having with the Try function and why it's not working as I would expect it.

Dropping the expression into a code editor, it appears you're missing....10 closing parentheses throughout the expression. So that's the immediate answer to your question.

But I'd strongly consider reworking the approach here, this will be immensely hard to maintain in the future.

3 Likes

I don't think I'm missing any parentheses. I mean it works if I remove the Try function. I don't get a bad expression error message.

My mistake, VSCode was rendering open/close parentheses pairs incorrectly. Ctrl+F indicated that you have an equal number of them. All 111 pairs.

Perhaps there's a soft limit to how deep you can nest in a Try expression? Seems unlikely but I've been surprised before. The devs might be able to speak on that.

Otherwise, I don't have much to offer beyond my initial comment

I just tried replacing the If statement inside the dateformat function with now() and it worked. So, there is something with If statement being nested causing the failover result when using the Try function.

You could probably clean this up with timeBetween().

You may be right with the limitation of the Try function based on what I previously mentioned with the test I did.

You really owe it to whoever has to maintain this after you to fix it. It's a horrible mess.

Then why are there 30 instances of todate(tostr(dateformat({[.]Production Shift 1/Working Date}, 'MM/dd/yyyy')))?

The time gets appended to it then converted back to a date.

timeBetween() would eliminate having to use the specific date for each one.

1 Like

For your own sake and that of everyone who comes after you, extract this into multiple intermediate 'stages' using intermediate custom properties. It's so much easier to debug an expression that's layered together like that than a single monolithic one like this.

13 Likes

If you do leave as-is, please add a comment above the code that includes your name, address and phone number. :slight_smile:

13 Likes

I've been pretty deep into the expression language for module development, and as far as I know there is no such nesting limitation. Obviously, I'm don't have the same knowledge as some of the IA devs. I'm pretty confident though.

Too my eyes there are some things here that can be changed.

For instance, why use tostr() on dateformat()? It already returns a string value.
And why convert a date (pretty sure it is a date) to a string, just to add hours to it and then convert it back? There is quite literally an addHours expression for that purpose.

I think you can cut a lot of your expression down make it far more readable and manageable.

If as @transistor suggested, we just work with dates as dates and we use the expressions to do so, then your expression can be paired down significantly to this:

try(
	if(
		dateIsAfter(
			now(),
			addHours(
				if( dateIsAfter(
						addHours({[.]Production Shift 1/Working Date},toInt({[.]Production Shift 1/Hours/Breaks}[5,4])),
						midnight({[.]Production Shift 1/Working Date})
					)
					&& dateIsBefore(
						addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[5,4])),
						addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[0,4]))
					),
					addDays({[.]Production Shift 1/Working Date},1),
					{[.]Production Shift 1/Working Date}
				),
				toInt({[.]Production Shift 1/Hours/Breaks}[5,4])
			))
		)
		&& dateIsBefore(
			now(),
			addHours(
				if( dateIsAfter(
						addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[5,5])),
						midnight({[.]Production Shift 1/Working Date})
					)
					&& dateIsBefore(
						addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[5,5])),
						addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[0,4]))
					),
					addDays({[.]Production Shift 1/Working Date},1),
					{[.]Production Shift 1/Working Date}
				), 
				toInt({[.]Production Shift 1/Hours/Breaks}[5,5])
			))
		&& {[.]Production Shift 1/Hours/Shift Var} != 11,
		secondsbetween(
			now(), 
			addHours(
				if( dateIsAfter(
						addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[5,5])),
						midnight({[.]Production Shift 1/Working Date})
					)
					&& dateIsBefore(
						addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[5,5])),
						addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[0,4]))
					),
					addDays({[.]Production Shift 1/Working Date},1), 
					{[.]Production Shift 1/Working Date}
				), 
				toInt({[.]Production Shift 1/Hours/Breaks}[5,5])
			),
		),
		if( dateIsBefore(
					now(),
					addHours(
						if(dateIsAfter(
								addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[5,4])),
								midnight({[.]Production Shift 1/Working Date})
							)
							&& dateIsBefore(
								addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[5,4])),
								addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[0,4]))
							),
							addDays({[.]Production Shift 1/Working Date},1), 
							{[.]Production Shift 1/Working Date}
						), 
						toInt({[.]Production Shift 1/Hours/Breaks}[5,4])
					)
				), 
			secondsBetween(
				addHours(
					if(dateIsAfter(
							addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks})),
							midnight({[.]Production Shift 1/Working Date})
						)
						&& dateIsBefore(
							addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[5,4]))
							addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[0,4]))
						),
						addDays({[.]Production Shift 1/Working Date},1), 
						toInt({[.]Production Shift 1/Working Date})
					)
					toInt({[.]Production Shift 1/Hours/Breaks}[5,4])
				),
				addHours(
					if(dateIsAfter(
							addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[5,5])),
							midnight({[.]Production Shift 1/Working Date})
						)
						&& dateIsBefore(
							addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[5,5])),
							addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[0,4]))
						),
						addDays({[.]Production Shift 1/Working Date},1), 
						{[.]Production Shift 1/Working Date}
					), 
					toInt({[.]Production Shift 1/Hours/Breaks}[5,5])
				),
			),
		0)
	),
99)

I don't know about you, but I find that a lot more readable.

If you follow @PGriffith's advice, hopefully now you can better see that there is a lot of receptiveness in this expression, that could be factored out to other expression tags.

Specifically the parts like this:

addHours(
	if( dateIsAfter(
			addHours({[.]Production Shift 1/Working Date},toInt({[.]Production Shift 1/Hours/Breaks}[5,4])),
			midnight({[.]Production Shift 1/Working Date})
		)
		&& dateIsBefore(
			addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[5,4])),
			addHours({[.]Production Shift 1/Working Date}, toInt({[.]Production Shift 1/Hours/Breaks}[0,4]))
		),
		addDays({[.]Production Shift 1/Working Date},1),
		{[.]Production Shift 1/Working Date}
	),
	toInt({[.]Production Shift 1/Hours/Breaks}[5,4])
)

Then your final expression becomes something like:

try(
    if( dateIsAfter(now(), someDate1) 
       && dateIsBefore(now(), someDate2)
       && {[.]Production Shift 1/Shift Var} != 11,
       secondsBetween(now(), someDate2),
       if(dateIsBefore(now(),someDate1),
           secondsBetween(someDate1, someDate2),
          0)
    ),
    99
)

Which is far, far better, to work with.

NOTE: Obviously, I did not test this, but I did my best to insure that the logic stayed in tact. Do your own testing and adjust as needed.

5 Likes

Can someone enlighten me. What does the [5, 4] syntax do? I don't think I've come across it before.

This is the expression equivalent of dataset.getValueAt(row, column). I use it occasionally and always forget which number is the row and which is the column.

3 Likes

Thanks. I didn't realise the tag was a dataset.

5 Likes