class TimeZoneParser {

    public static final DateTimeZone DEFAULT_TZ = DateTimeZone.UTC;
    public static final Literal<String> DEFAULT_TZ_LITERAL = Literal.of("UTC");

    private static final ConcurrentMap<String, DateTimeZone> TIME_ZONE_MAP = new ConcurrentHashMap<>();

    private TimeZoneParser() {
    }

    public static DateTimeZone parseTimeZone(String timezone) throws IllegalArgumentException {<FILL_FUNCTION_BODY>}
}

        if (timezone == null) {
            throw new IllegalArgumentException("invalid time zone value NULL");
        }
        if (timezone.equals(DEFAULT_TZ_LITERAL.value())) {
            return DEFAULT_TZ;
        }

        DateTimeZone tz = TIME_ZONE_MAP.get(timezone);
        if (tz == null) {
            try {
                int index = timezone.indexOf(':');
                if (index != -1) {
                    int beginIndex = timezone.charAt(0) == '+' ? 1 : 0;
                    // format like -02:30
                    tz = DateTimeZone.forOffsetHoursMinutes(
                        Integer.parseInt(timezone.substring(beginIndex, index)),
                        Integer.parseInt(timezone.substring(index + 1))
                    );
                } else {
                    // id, listed here: http://joda-time.sourceforge.net/timezones.html
                    // or here: http://www.joda.org/joda-time/timezones.html
                    tz = DateTimeZone.forID(timezone);
                }
            } catch (IllegalArgumentException e) {
                throw new IllegalArgumentException(String.format(Locale.ENGLISH,
                    "invalid time zone value '%s'", timezone));
            }
            TIME_ZONE_MAP.putIfAbsent(timezone, tz);
        }
        return tz;
    
<no_super_class>