Why isn’t my rewrite rule working when there is no second parameter?

Your regular expression is requiring the last slash be present which it will not be by default. So the path tides/mylocation/ is shortened to tides/mylocation and then tested. Instead, wrap the last part in an optional group using the ? and update the match number.

add_rewrite_rule('tides/([^/]+)(/([^/]+))?', 'index.php?page_id=4348&location=$matches[1]&month=$matches[3]', 'top');