// Path: src/main/java/com/orgzly/org/OrgPatterns.java
// public class OrgPatterns {
//     // org-ts-regexp-both
//     private static final String DT = "(([\\[<])[0-9]{4,}-[0-9]{2}-[0-9]{2} ?[^]\r\n>]*?[]>])";
// 
//     // org-tsr-regexp-both
//     private static final String DT_OR_RANGE = "(" + DT + "(--?-?" + DT + ")?)";
// 
//     public static final Pattern DT_OR_RANGE_P = Pattern.compile(OrgPatterns.DT_OR_RANGE);
// 
//     //  org-repeat-re
//     public static final Pattern REPEAT_P = Pattern.compile(
//             "[0-9]{4,}-[0-9][0-9]-[0-9][0-9] [^>\n]*?([.+]?\\+[0-9]+[hdwmy](/[0-9]+[hdwmy])?)");
// 
//     public static final Pattern TIME_DELAY_P = Pattern.compile("([-]{1,2}+)([0-9]+)([hdwmy])");
// 
//     public static final Pattern REPEATER = Pattern.compile(
//             "(([.+]?\\+)([0-9]+)([hdwmy]))(/([0-9]+)([hdwmy]))?");
// 
//     // org-ts-regexp0
//     public static final Pattern DT_MAYBE_WITH_TIME_P = Pattern.compile(
//             "(([0-9]{4,})-([0-9]{2})-([0-9]{2})( +[^]+0-9>\r\n -]+)?( +([0-9]{1,2}):([0-9]{2}))?)");
// 
//     /*
//      * Time of day with optional end-time.
//      * From org-get-compact-tod.
//      */
//     public static final Pattern TIME_OF_DAY_P = Pattern.compile(
//             "(([012]?[0-9]):([0-5][0-9]))(-(([012]?[0-9]):([0-5][0-9])))?");
// 
//     public static final Pattern PLANNING_TIMES_P = Pattern.compile(
//             "(SCHEDULED:|CLOSED:|DEADLINE:) *" + DT_OR_RANGE);
// 
//     public static final Pattern HEAD_P = Pattern.compile("^([*]+)\\s+(.*)\\s*$");
//     public static final Pattern HEAD_PRIORITY_P = Pattern.compile("^\\s*\\[#([A-Z])](.*)");
//     public static final Pattern HEAD_TAGS_P = Pattern.compile("^(.*)\\s+:(\\S+):\\s*$");
// 
//     // org-property-re
//     public static final Pattern PROPERTY = Pattern.compile("^[ \\t]*:(\\S+):(|[ \\t]+.*?[ \\t]*)$");
// 
//     /*
//     https://orgmode.org/manual/In_002dbuffer-settings.html
// 
//     "In-buffer settings start with ‘#+’, followed by a keyword, a colon,
//     and then a word for each setting. Org accepts multiple settings on the same line.
//     Org also accepts multiple lines for a keyword."
// 
//     Here we don't allow multiple settings per line for now.
//      */
//     public static final Pattern KEYWORD_VALUE = Pattern.compile("^#\\+([A-Za-z0-9_]+):\\s*(.*?)\\s*$");
// }
// 
// Path: src/main/java/com/orgzly/org/OrgStringUtils.java
// public class OrgStringUtils {
//     public static String trimLines(String str) {
//         return str.replaceFirst("\n+[\\s]*$", "").replaceFirst("^[\\s]*\n", "");
//     }
// 
//     public static boolean isEmpty(String s) {
//         return s == null || s.length() == 0;
//     }
// 
//     public static String join(Collection set, String d) {
//         StringBuilder result = new StringBuilder();
// 
//         int i = 0;
//         for (Object str: set) {
//             result.append(str);
// 
//             if (i++ < set.size() - 1) { /* Not last. */
//                 result.append(d);
//             }
//         }
// 
//         return result.toString();
//     }
// 
// 
// 
//     public static int stringWidth(String str) {
//         int total = 0;
// 
//         for (int i = 0; i < str.length(); ) {
//             int cp = str.codePointAt(i);
// 
//             int width = codePointWidth(cp);
// 
//             // System.out.printf("Code point %c width: %d\n", cp, width);
// 
//             total += width;
// 
//             i += Character.charCount(cp);
//         }
// 
//         return total;
//     }
// 
//     private static int codePointWidth(int cp) {
//         return EastAsianWidth.CP.contains(cp) ? 2 : 1;
//     }
// }


import com.orgzly.org.OrgPatterns;
import com.orgzly.org.OrgStringUtils;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
            if (string == null) {
                throw new IllegalStateException("Missing string");
            }

            parseString();
        }
    }

    /**
     * Parse {@link OrgDateTime#string} and populate other fields.
     */
    private void parseString() {
        Matcher m;

        cal = Calendar.getInstance();
        endCal = null;

        switch (string.charAt(0)) {
            case '<':
                isActive = true;
                break;

            case '[':
                isActive = false;
                break;

            default:
                throw new IllegalArgumentException("Timestamp \"" + string + "\" must start with < or [");
        }

// Path: src/main/java/com/orgzly/org/OrgPatterns.java
// public class OrgPatterns {
//     // org-ts-regexp-both
//     private static final String DT = "(([\\[<])[0-9]{4,}-[0-9]{2}-[0-9]{2} ?[^]\r\n>]*?[]>])";
// 
//     // org-tsr-regexp-both
//     private static final String DT_OR_RANGE = "(" + DT + "(--?-?" + DT + ")?)";
// 
//     public static final Pattern DT_OR_RANGE_P = Pattern.compile(OrgPatterns.DT_OR_RANGE);
// 
//     //  org-repeat-re
//     public static final Pattern REPEAT_P = Pattern.compile(
//             "[0-9]{4,}-[0-9][0-9]-[0-9][0-9] [^>\n]*?([.+]?\\+[0-9]+[hdwmy](/[0-9]+[hdwmy])?)");
// 
//     public static final Pattern TIME_DELAY_P = Pattern.compile("([-]{1,2}+)([0-9]+)([hdwmy])");
// 
//     public static final Pattern REPEATER = Pattern.compile(
//             "(([.+]?\\+)([0-9]+)([hdwmy]))(/([0-9]+)([hdwmy]))?");
// 
//     // org-ts-regexp0
//     public static final Pattern DT_MAYBE_WITH_TIME_P = Pattern.compile(
//             "(([0-9]{4,})-([0-9]{2})-([0-9]{2})( +[^]+0-9>\r\n -]+)?( +([0-9]{1,2}):([0-9]{2}))?)");
// 
//     /*
//      * Time of day with optional end-time.
//      * From org-get-compact-tod.
//      */
//     public static final Pattern TIME_OF_DAY_P = Pattern.compile(
//             "(([012]?[0-9]):([0-5][0-9]))(-(([012]?[0-9]):([0-5][0-9])))?");
// 
//     public static final Pattern PLANNING_TIMES_P = Pattern.compile(
//             "(SCHEDULED:|CLOSED:|DEADLINE:) *" + DT_OR_RANGE);
// 
//     public static final Pattern HEAD_P = Pattern.compile("^([*]+)\\s+(.*)\\s*$");
//     public static final Pattern HEAD_PRIORITY_P = Pattern.compile("^\\s*\\[#([A-Z])](.*)");
//     public static final Pattern HEAD_TAGS_P = Pattern.compile("^(.*)\\s+:(\\S+):\\s*$");
// 
//     // org-property-re
//     public static final Pattern PROPERTY = Pattern.compile("^[ \\t]*:(\\S+):(|[ \\t]+.*?[ \\t]*)$");
// 
//     /*
//     https://orgmode.org/manual/In_002dbuffer-settings.html
// 
//     "In-buffer settings start with ‘#+’, followed by a keyword, a colon,
//     and then a word for each setting. Org accepts multiple settings on the same line.
//     Org also accepts multiple lines for a keyword."
// 
//     Here we don't allow multiple settings per line for now.
//      */
//     public static final Pattern KEYWORD_VALUE = Pattern.compile("^#\\+([A-Za-z0-9_]+):\\s*(.*?)\\s*$");
// }
// 
// Path: src/main/java/com/orgzly/org/OrgStringUtils.java
// public class OrgStringUtils {
//     public static String trimLines(String str) {
//         return str.replaceFirst("\n+[\\s]*$", "").replaceFirst("^[\\s]*\n", "");
//     }
// 
//     public static boolean isEmpty(String s) {
//         return s == null || s.length() == 0;
//     }
// 
//     public static String join(Collection set, String d) {
//         StringBuilder result = new StringBuilder();
// 
//         int i = 0;
//         for (Object str: set) {
//             result.append(str);
// 
//             if (i++ < set.size() - 1) { /* Not last. */
//                 result.append(d);
//             }
//         }
// 
//         return result.toString();
//     }
// 
// 
// 
//     public static int stringWidth(String str) {
//         int total = 0;
// 
//         for (int i = 0; i < str.length(); ) {
//             int cp = str.codePointAt(i);
// 
//             int width = codePointWidth(cp);
// 
//             // System.out.printf("Code point %c width: %d\n", cp, width);
// 
//             total += width;
// 
//             i += Character.charCount(cp);
//         }
// 
//         return total;
//     }
// 
//     private static int codePointWidth(int cp) {
//         return EastAsianWidth.CP.contains(cp) ? 2 : 1;
//     }
// }


// Path: src/main/java/com/orgzly/org/datetime/OrgDateTime.java
import com.orgzly.org.OrgPatterns;
import com.orgzly.org.OrgStringUtils;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

            if (string == null) {
                throw new IllegalStateException("Missing string");
            }

            parseString();
        }
    }

    /**
     * Parse {@link OrgDateTime#string} and populate other fields.
     */
    private void parseString() {
        Matcher m;

        cal = Calendar.getInstance();
        endCal = null;

        switch (string.charAt(0)) {
            case '<':
                isActive = true;
                break;

            case '[':
                isActive = false;
                break;

            default:
                throw new IllegalArgumentException("Timestamp \"" + string + "\" must start with < or [");
        }

        m = OrgPatterns.DT_MAYBE_WITH_TIME_P.matcher(string);