contract TimedCrowdsale is SoftcappedCrowdsale {
    using SafeMath for uint256;

    uint256 private _openingTime;
    uint256 private _softcapDeadline;
    uint256 private _closingTime;

    /**
     * Event for crowdsale extending
     * @param newClosingTime new closing time
     * @param prevClosingTime old closing time
     */
    event TimedCrowdsaleExtended(uint256 prevClosingTime, uint256 newClosingTime);

    /**
     * @dev Reverts if not in crowdsale time range.
     */
    modifier onlyWhileOpen {
        require(!hasClosed());
        _;
    }

    /**
     * @dev Constructor, takes crowdsale opening and closing times.
     * @param openingTime Crowdsale opening time
     * @param softcapDeadline Crowdsale closing time
     */
    constructor (uint256 openingTime, uint256 softcapDeadline, uint256 closingTime) public {
        // solhint-disable-next-line not-rely-on-time
        //todo require(openingTime >= block.timestamp);
        require(softcapDeadline > openingTime);
        require(closingTime > softcapDeadline);

        _openingTime = openingTime;
        _softcapDeadline = softcapDeadline;
        _closingTime = closingTime;
    }

    /**
     * @return the crowdsale opening time.
     */
    function openingTime() public view returns (uint256) {
        return _openingTime;
    }

    /**
     * @return the crowdsale softcap deadline.
     */
    function softcapDeadline() public view returns (uint256) {
        return _softcapDeadline;
    }

    /**
     * @return the crowdsale closing time.
     */
    function closingTime() public view returns (uint256) {
        return _closingTime;
    }


    /**
     * @dev Checks whether the period in which the crowdsale is open has already elapsed.
     * @return Whether crowdsale period has elapsed and goal hasn't been reached
     */
    function hasClosed() public view returns (bool) {
        // solhint-disable-next-line not-rely-on-time
        return ((block.timestamp > _softcapDeadline) && !goalReached()) ||
        ((block.timestamp > _closingTime) && goalReached());
    }

    /**
     * @dev Extend parent behavior requiring to be within contributing period
     * @param beneficiary Token purchaser
     * @param weiAmount Amount of wei contributed
     */
    function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal onlyWhileOpen view {
        super._preValidatePurchase(beneficiary, weiAmount);
    }


}
/**
 * @title TimedCrowdsale
 * @dev Crowdsale closes if softcap not reached within a time frame.
 */
function openingTime() public view returns (uint256) {
    return _openingTime;
}

/**
 * @return the crowdsale opening time.
 */