Scheduling a task into a period within a day, depending on whether or not it is a weekend I have a function which needs to detect part of the day depending on whether it's the weekend or not (the weekend affects the lunch time indication). The method is quite long and I'd like to know how it can be better.

double PartOfDayRule::ExtractFeature(dto::ActionableItem &amp; item) {
                double morning, firstWorkPart, lunch, secondWorkPart, afterWork, beforeSleep, sleepTime;
                morning = 0;
                firstWorkPart = 1;
                lunch = 2;
                secondWorkPart = 3;
                afterWork = 4;
                beforeSleep = 5;
                sleepTime = 6;

                double result = -1;
                dto::DateTime itemTime = item.scheduledStart;
                if(util::time::inRange(item.ctx-&gt;sleepTimeEnd, item.ctx-&gt;workTimeStart, itemTime)){
                    result = morning;
                    goto result;
                }

                dto::DateTime lunchStart;
                dto::DateTime lunchStop;
                if(!item.ctx-&gt;isWorkingDay){
                    lunchStart = item.ctx-&gt;workTimeStart;
                    lunchStop = item.ctx-&gt;workTimeFinished;
                }else{
                    long firstWorkPartLength = util::time::between&lt;std::chrono::hours&gt;(item.ctx-&gt;workTimeStart, item.ctx-&gt;workTimeFinished) / 2;
                    lunchStart = item.ctx-&gt;workTimeStart + std::chrono::hours{firstWorkPartLength};
                    lunchStop = lunchStart + std::chrono::hours{1};
                }
                if(util::time::inRange(lunchStart, lunchStop, itemTime)){
                    result = lunch;
                    goto result;
                }

                if(util::time::inRange(item.ctx-&gt;workTimeStart, lunchStart, itemTime)){
                    result = firstWorkPart;
                    goto result;
                }

                if(util::time::inRange(lunchStop, item.ctx-&gt;workTimeFinished, itemTime)){
                    result = secondWorkPart;
                    goto result;
                }

                dto::DateTime sleepPreparationTime = item.ctx-&gt;sleepTimeStart - std::chrono::hours{1};
                if(util::time::inRange(item.ctx-&gt;workTimeFinished, sleepPreparationTime, itemTime)){
                    result = afterWork;
                    goto result;
                }

                if(util::time::inRange(sleepPreparationTime, item.ctx-&gt;sleepTimeStart, itemTime)){
                    result = beforeSleep;
                    goto result;
                }

                result = sleepTime;
                result:
                return result;

            }
You return what is effectively an enum as a double. Why? create the enum and return that it's much clearer that way wat the return value means:

If you still want a single point of return (for whatever reason) then you can use an if-else chain:

enum PartOfDay{
    morning = 0,
    firstWorkPart = 1,
    lunch = 2,
    secondWorkPart = 3,
    afterWork = 4,
    beforeSleep = 5,
    sleepTime = 6
}

PartOfDay PartOfDayRule::ExtractFeature(dto::ActionableItem &amp; item) {

    dto::DateTime lunchStart;
    dto::DateTime lunchStop;
    if(!item.ctx-&gt;isWorkingDay){
        lunchStart = item.ctx-&gt;workTimeStart;
        lunchStop = item.ctx-&gt;workTimeFinished;
    }else{
        long firstWorkPartLength = util::time::between&lt;std::chrono::hours&gt;(item.ctx-&gt;workTimeStart, item.ctx-&gt;workTimeFinished) / 2;
        lunchStart = item.ctx-&gt;workTimeStart + std::chrono::hours{firstWorkPartLength};
        lunchStop = lunchStart + std::chrono::hours{1};
    }

    dto::DateTime itemTime = item.scheduledStart;
    dto::DateTime sleepPreparationTime = item.ctx-&gt;sleepTimeStart - std::chrono::hours{1};
    PartOfDay result = sleepTime;

    if(util::time::inRange(item.ctx-&gt;sleepTimeEnd, item.ctx-&gt;workTimeStart, itemTime)){
        result = morning;
    } else if(util::time::inRange(item.ctx-&gt;workTimeStart, lunchStart, itemTime)){
        result = firstWorkPart;
    } else if(util::time::inRange(lunchStart, lunchStop, itemTime)){
        result = lunch;
    } else if(util::time::inRange(lunchStop, item.ctx-&gt;workTimeFinished, itemTime)){
        result = secondWorkPart;
    }else if(util::time::inRange(item.ctx-&gt;workTimeFinished, sleepPreparationTime, itemTime)){
        result = afterWork;
    }else if(util::time::inRange(sleepPreparationTime, item.ctx-&gt;sleepTimeStart, itemTime)){
        result = beforeSleep;
    }else {
        result = sleepTime;
    }
    return result;

} 


Or you can sort the ranges and then use std::find to get the range you want.