Finally I got the solution and here is how I reach there.
Problem with recursion depth error with flask is its not easy to get root cause of problem, so with hit and trial approach I got tail of the problem.
Method call flow is like this:
dateformat filter > format_date() > to_user_timezone() > get_timezone()
Now get timezone method is overridden here as:
def get_timezone():
"""
Returns the timezone that should be used for this request as
`pytz.timezone` object. This returns `None` if used outside of
a request.
"""
ctx = _request_ctx_stack.top
tzinfo = getattr(ctx, 'babel_tzinfo', None)
if tzinfo is None:
babel = ctx.app.extensions['babel']
if babel.timezone_selector_func is None:
if not current_user.is_anonymous() and current_user.timezone:
tzinfo = timezone(current_user.timezone)
else:
tzinfo = timezone(ctx.request.nereid_website.timezone)
else:
rv = babel.timezone_selector_func()
if rv is None:
tzinfo = babel.default_timezone
else:
if isinstance(rv, basestring):
tzinfo = timezone(rv)
else:
tzinfo = rv
ctx.babel_tzinfo = tzinfo
return tzinfo
flask.ext.babel.get_timezone = get_timezone
From here it is calling a function field timezone in nereid_website, which by default returning company's timezone, a field which is not required.
Finally, I have fixed this issue in PR#229. Welcome reviewers!