/*
 * SDK Pullenti Lingvo, version 4.33, fabruary 2026. Copyright (c) 2013-2026, Pullenti. All rights reserved. 
 * Non-Commercial Freeware and Commercial Software.
 * This class is generated using the converter Unisharping (www.unisharping.ru) from Pullenti C# project. 
 * The latest version of the code is available on the site www.pullenti.ru
 */

package com.pullenti.ner.date.internal;

public class DateRelHelper {

    public static java.util.ArrayList<com.pullenti.ner.ReferentToken> createReferents(DateExToken et) {
        if (!et.isDiap || et.itemsTo.size() == 0) {
            java.util.ArrayList<com.pullenti.ner.ReferentToken> li = _createRefs(et.itemsFrom);
            if (li == null || li.size() == 0) 
                return null;
            return li;
        }
        java.util.ArrayList<com.pullenti.ner.ReferentToken> liFr = _createRefs(et.itemsFrom);
        java.util.ArrayList<com.pullenti.ner.ReferentToken> liTo = _createRefs(et.itemsTo);
        com.pullenti.ner.date.DateRangeReferent ra = new com.pullenti.ner.date.DateRangeReferent();
        if (liFr.size() > 0) 
            ra.setDateFrom((com.pullenti.ner.date.DateReferent)com.pullenti.unisharp.Utils.cast(liFr.get(0).tag, com.pullenti.ner.date.DateReferent.class));
        if (liTo.size() > 0) 
            ra.setDateTo((com.pullenti.ner.date.DateReferent)com.pullenti.unisharp.Utils.cast(liTo.get(0).tag, com.pullenti.ner.date.DateReferent.class));
        java.util.ArrayList<com.pullenti.ner.ReferentToken> res = new java.util.ArrayList<com.pullenti.ner.ReferentToken>();
        com.pullenti.unisharp.Utils.addToArrayList(res, liFr);
        com.pullenti.unisharp.Utils.addToArrayList(res, liTo);
        res.add(new com.pullenti.ner.ReferentToken(ra, et.getBeginToken(), et.getEndToken(), null));
        if (res.size() == 0) 
            return null;
        res.get(0).tag = ra;
        return res;
    }

    private static java.util.ArrayList<com.pullenti.ner.ReferentToken> _createRefs(java.util.ArrayList<DateExToken.DateExItemToken> its) {
        java.util.ArrayList<com.pullenti.ner.ReferentToken> res = new java.util.ArrayList<com.pullenti.ner.ReferentToken>();
        com.pullenti.ner.date.DateReferent own = null;
        for (int i = 0; i < its.size(); i++) {
            DateExToken.DateExItemToken it = its.get(i);
            com.pullenti.ner.date.DateReferent d = new com.pullenti.ner.date.DateReferent();
            if (it.isValueRelate) 
                d.setRelative(true);
            if (own != null) 
                d.setHigher(own);
            if (it.typ == DateExToken.DateExItemTokenType.DAY) {
                d.setDay(it.value);
                if (it.isLast && ((it.value == 0 || it.value == -1)) && i > 0) {
                    DateExToken.DateExItemToken it0 = its.get(i - 1);
                    int day = 0;
                    if (it0.typ == DateExToken.DateExItemTokenType.MONTH && !it0.isValueRelate) {
                        int m = d.getMonth();
                        if (((m == 1 || m == 3 || m == 5) || m == 7 || m == 8) || m == 10 || m == 12) 
                            day = 31;
                        else if (m == 2) 
                            day = 28;
                        else if (m > 0) 
                            day = 30;
                    }
                    else if (it0.typ == DateExToken.DateExItemTokenType.QUARTAL && !it0.isValueRelate) {
                        int m = 1 + (((it0.value - 1)) * 4);
                        com.pullenti.ner.date.DateReferent dm = new com.pullenti.ner.date.DateReferent();
                        dm.setMonth(m);
                        if (own != null) 
                            dm.setHigher(own);
                        res.add(new com.pullenti.ner.ReferentToken(dm, it.getBeginToken(), it.getEndToken(), null));
                        own = d.setHigher(dm);
                        if (((m == 1 || m == 3 || m == 5) || m == 7 || m == 8) || m == 10 || m == 12) 
                            day = 31;
                        else if (m == 2) 
                            day = 28;
                        else if (m > 0) 
                            day = 30;
                    }
                    else if (it0.typ == DateExToken.DateExItemTokenType.YEAR) {
                        com.pullenti.ner.date.DateReferent dm = new com.pullenti.ner.date.DateReferent();
                        dm.setMonth(12);
                        if (own != null) 
                            dm.setHigher(own);
                        res.add(new com.pullenti.ner.ReferentToken(dm, it.getBeginToken(), it.getEndToken(), null));
                        own = d.setHigher(dm);
                        day = 31;
                    }
                    else if (it0.typ == DateExToken.DateExItemTokenType.CENTURY) {
                        com.pullenti.ner.date.DateReferent dy = new com.pullenti.ner.date.DateReferent();
                        dy.setYear(99);
                        dy.setRelative(true);
                        if (own != null) 
                            dy.setHigher(own);
                        res.add(new com.pullenti.ner.ReferentToken(dy, it.getBeginToken(), it.getEndToken(), null));
                        own = dy;
                        com.pullenti.ner.date.DateReferent dm = new com.pullenti.ner.date.DateReferent();
                        dm.setMonth(12);
                        dm.setHigher(own);
                        res.add(new com.pullenti.ner.ReferentToken(dm, it.getBeginToken(), it.getEndToken(), null));
                        own = d.setHigher(dm);
                        day = 31;
                    }
                    if ((day + it.value) > 0) {
                        d.setRelative(false);
                        d.setDay(day + it.value);
                    }
                }
            }
            else if (it.typ == DateExToken.DateExItemTokenType.DAYOFWEEK) 
                d.setDayOfWeek(it.value);
            else if (it.typ == DateExToken.DateExItemTokenType.HOUR) {
                d.setHour(it.value);
                if (((i + 1) < its.size()) && its.get(i + 1).typ == DateExToken.DateExItemTokenType.MINUTE && !its.get(i + 1).isValueRelate) {
                    d.setMinute(its.get(i + 1).value);
                    i++;
                }
            }
            else if (it.typ == DateExToken.DateExItemTokenType.MINUTE) 
                d.setMinute(it.value);
            else if (it.typ == DateExToken.DateExItemTokenType.MONTH) {
                d.setMonth(it.value);
                if (it.isLast && ((it.value == 0 || it.value == -1)) && i > 0) {
                    DateExToken.DateExItemToken it0 = its.get(i - 1);
                    int m = 0;
                    if (it0.typ == DateExToken.DateExItemTokenType.QUARTAL && !it0.isValueRelate) 
                        m = 1 + (((it0.value - 1)) * 4) + it.value;
                    else if (it0.typ == DateExToken.DateExItemTokenType.YEAR || it0.typ == DateExToken.DateExItemTokenType.DECADE || it0.typ == DateExToken.DateExItemTokenType.CENTURY) 
                        m = 12 + it.value;
                    if (m > 0) {
                        d.setRelative(false);
                        d.setMonth(m);
                    }
                }
            }
            else if (it.typ == DateExToken.DateExItemTokenType.QUARTAL) 
                d.setQuartal(it.value);
            else if (it.typ == DateExToken.DateExItemTokenType.SEASON) 
                d.setSeason(it.value);
            else if (it.typ == DateExToken.DateExItemTokenType.WEEK) 
                d.setWeek(it.value);
            else if (it.typ == DateExToken.DateExItemTokenType.HALFYEAR) 
                d.setHalfyear((it.isLast ? 2 : it.value));
            else if (it.typ == DateExToken.DateExItemTokenType.YEAR) 
                d.setYear(it.value);
            else if (it.typ == DateExToken.DateExItemTokenType.CENTURY) 
                d.setCentury(it.value);
            else if (it.typ == DateExToken.DateExItemTokenType.DECADE) 
                d.setDecade(it.value);
            else 
                continue;
            res.add(new com.pullenti.ner.ReferentToken(d, it.getBeginToken(), it.getEndToken(), null));
            own = d;
            it.src = d;
        }
        if (res.size() > 0) 
            res.get(0).tag = own;
        return res;
    }

    private static java.util.ArrayList<DateExToken.DateExItemToken> _createDateEx(com.pullenti.ner.date.DateReferent dr) {
        java.util.ArrayList<DateExToken.DateExItemToken> res = new java.util.ArrayList<DateExToken.DateExItemToken>();
        for (; dr != null; dr = dr.getHigher()) {
            int n;
            for (com.pullenti.ner.Slot s : dr.getSlots()) {
                com.pullenti.ner.Token tt = new com.pullenti.ner.Token(null, 0, 1);
                DateExToken.DateExItemToken it = DateExToken.DateExItemToken._new891(tt, tt, DateExToken.DateExItemTokenType.UNDEFINED);
                if (com.pullenti.unisharp.Utils.stringsEq(dr.getStringValue(com.pullenti.ner.date.DateReferent.ATTR_ISRELATIVE), "true")) 
                    it.isValueRelate = true;
                if (com.pullenti.unisharp.Utils.stringsEq(s.getTypeName(), com.pullenti.ner.date.DateReferent.ATTR_YEAR)) {
                    it.typ = DateExToken.DateExItemTokenType.YEAR;
                    com.pullenti.unisharp.Outargwrapper<Integer> wrapn892 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                    boolean inoutres893 = com.pullenti.unisharp.Utils.parseInteger((String)com.pullenti.unisharp.Utils.cast(s.getValue(), String.class), 0, null, wrapn892);
                    n = (wrapn892.value != null ? wrapn892.value : 0);
                    if (inoutres893) 
                        it.value = n;
                }
                else if (com.pullenti.unisharp.Utils.stringsEq(s.getTypeName(), com.pullenti.ner.date.DateReferent.ATTR_DECADE)) {
                    it.typ = DateExToken.DateExItemTokenType.DECADE;
                    com.pullenti.unisharp.Outargwrapper<Integer> wrapn894 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                    boolean inoutres895 = com.pullenti.unisharp.Utils.parseInteger((String)com.pullenti.unisharp.Utils.cast(s.getValue(), String.class), 0, null, wrapn894);
                    n = (wrapn894.value != null ? wrapn894.value : 0);
                    if (inoutres895) 
                        it.value = n;
                }
                else if (com.pullenti.unisharp.Utils.stringsEq(s.getTypeName(), com.pullenti.ner.date.DateReferent.ATTR_CENTURY)) {
                    it.typ = DateExToken.DateExItemTokenType.CENTURY;
                    com.pullenti.unisharp.Outargwrapper<Integer> wrapn896 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                    boolean inoutres897 = com.pullenti.unisharp.Utils.parseInteger((String)com.pullenti.unisharp.Utils.cast(s.getValue(), String.class), 0, null, wrapn896);
                    n = (wrapn896.value != null ? wrapn896.value : 0);
                    if (inoutres897) 
                        it.value = n;
                }
                else if (com.pullenti.unisharp.Utils.stringsEq(s.getTypeName(), com.pullenti.ner.date.DateReferent.ATTR_HALFYEAR)) {
                    it.typ = DateExToken.DateExItemTokenType.HALFYEAR;
                    com.pullenti.unisharp.Outargwrapper<Integer> wrapn898 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                    boolean inoutres899 = com.pullenti.unisharp.Utils.parseInteger((String)com.pullenti.unisharp.Utils.cast(s.getValue(), String.class), 0, null, wrapn898);
                    n = (wrapn898.value != null ? wrapn898.value : 0);
                    if (inoutres899) 
                        it.value = n;
                }
                else if (com.pullenti.unisharp.Utils.stringsEq(s.getTypeName(), com.pullenti.ner.date.DateReferent.ATTR_QUARTAL)) {
                    it.typ = DateExToken.DateExItemTokenType.QUARTAL;
                    com.pullenti.unisharp.Outargwrapper<Integer> wrapn900 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                    boolean inoutres901 = com.pullenti.unisharp.Utils.parseInteger((String)com.pullenti.unisharp.Utils.cast(s.getValue(), String.class), 0, null, wrapn900);
                    n = (wrapn900.value != null ? wrapn900.value : 0);
                    if (inoutres901) 
                        it.value = n;
                }
                else if (com.pullenti.unisharp.Utils.stringsEq(s.getTypeName(), com.pullenti.ner.date.DateReferent.ATTR_SEASON)) {
                    it.typ = DateExToken.DateExItemTokenType.SEASON;
                    com.pullenti.unisharp.Outargwrapper<Integer> wrapn902 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                    boolean inoutres903 = com.pullenti.unisharp.Utils.parseInteger((String)com.pullenti.unisharp.Utils.cast(s.getValue(), String.class), 0, null, wrapn902);
                    n = (wrapn902.value != null ? wrapn902.value : 0);
                    if (inoutres903) 
                        it.value = n;
                }
                else if (com.pullenti.unisharp.Utils.stringsEq(s.getTypeName(), com.pullenti.ner.date.DateReferent.ATTR_MONTH)) {
                    it.typ = DateExToken.DateExItemTokenType.MONTH;
                    com.pullenti.unisharp.Outargwrapper<Integer> wrapn904 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                    boolean inoutres905 = com.pullenti.unisharp.Utils.parseInteger((String)com.pullenti.unisharp.Utils.cast(s.getValue(), String.class), 0, null, wrapn904);
                    n = (wrapn904.value != null ? wrapn904.value : 0);
                    if (inoutres905) 
                        it.value = n;
                }
                else if (com.pullenti.unisharp.Utils.stringsEq(s.getTypeName(), com.pullenti.ner.date.DateReferent.ATTR_WEEK)) {
                    it.typ = DateExToken.DateExItemTokenType.WEEK;
                    com.pullenti.unisharp.Outargwrapper<Integer> wrapn906 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                    boolean inoutres907 = com.pullenti.unisharp.Utils.parseInteger((String)com.pullenti.unisharp.Utils.cast(s.getValue(), String.class), 0, null, wrapn906);
                    n = (wrapn906.value != null ? wrapn906.value : 0);
                    if (inoutres907) 
                        it.value = n;
                }
                else if (com.pullenti.unisharp.Utils.stringsEq(s.getTypeName(), com.pullenti.ner.date.DateReferent.ATTR_DAYOFWEEK)) {
                    it.typ = DateExToken.DateExItemTokenType.DAYOFWEEK;
                    com.pullenti.unisharp.Outargwrapper<Integer> wrapn908 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                    boolean inoutres909 = com.pullenti.unisharp.Utils.parseInteger((String)com.pullenti.unisharp.Utils.cast(s.getValue(), String.class), 0, null, wrapn908);
                    n = (wrapn908.value != null ? wrapn908.value : 0);
                    if (inoutres909) 
                        it.value = n;
                }
                else if (com.pullenti.unisharp.Utils.stringsEq(s.getTypeName(), com.pullenti.ner.date.DateReferent.ATTR_DAY)) {
                    it.typ = DateExToken.DateExItemTokenType.DAY;
                    com.pullenti.unisharp.Outargwrapper<Integer> wrapn910 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                    boolean inoutres911 = com.pullenti.unisharp.Utils.parseInteger((String)com.pullenti.unisharp.Utils.cast(s.getValue(), String.class), 0, null, wrapn910);
                    n = (wrapn910.value != null ? wrapn910.value : 0);
                    if (inoutres911) 
                        it.value = n;
                }
                else if (com.pullenti.unisharp.Utils.stringsEq(s.getTypeName(), com.pullenti.ner.date.DateReferent.ATTR_HOUR)) {
                    it.typ = DateExToken.DateExItemTokenType.HOUR;
                    com.pullenti.unisharp.Outargwrapper<Integer> wrapn912 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                    boolean inoutres913 = com.pullenti.unisharp.Utils.parseInteger((String)com.pullenti.unisharp.Utils.cast(s.getValue(), String.class), 0, null, wrapn912);
                    n = (wrapn912.value != null ? wrapn912.value : 0);
                    if (inoutres913) 
                        it.value = n;
                }
                else if (com.pullenti.unisharp.Utils.stringsEq(s.getTypeName(), com.pullenti.ner.date.DateReferent.ATTR_MINUTE)) {
                    it.typ = DateExToken.DateExItemTokenType.MINUTE;
                    com.pullenti.unisharp.Outargwrapper<Integer> wrapn914 = new com.pullenti.unisharp.Outargwrapper<Integer>();
                    boolean inoutres915 = com.pullenti.unisharp.Utils.parseInteger((String)com.pullenti.unisharp.Utils.cast(s.getValue(), String.class), 0, null, wrapn914);
                    n = (wrapn914.value != null ? wrapn914.value : 0);
                    if (inoutres915) 
                        it.value = n;
                }
                if (it.typ != DateExToken.DateExItemTokenType.UNDEFINED) 
                    res.add(0, it);
            }
        }
        // PYTHON: sort(key=attrgetter('typ'))
        java.util.Collections.sort(res);
        return res;
    }

    public static java.time.LocalDateTime calculateDate(com.pullenti.ner.date.DateReferent dr, java.time.LocalDateTime now, int tense, int fromto) {
        if (dr.getPointer() == com.pullenti.ner.date.DatePointerType.TODAY) 
            return now;
        if (!dr.isRelative()) {
            int year = dr.getYear();
            if (year < 1) 
                return null;
            int mon = dr.getMonth();
            if (mon < 1) 
                mon = (fromto == 1 ? 12 : 1);
            int day = dr.getDay();
            if (day < 1) 
                day = (fromto == 1 ? 31 : 1);
            try {
                return java.time.LocalDateTime.of(year, mon, day, 0, 0, 0);
            } catch (Exception ex916) {
            }
            return null;
        }
        DateExToken det = new DateExToken(null, null);
        det.itemsFrom = _createDateEx(dr);
        return det.getDate(now, tense);
    }

    public static boolean calculateDateRange(com.pullenti.ner.date.DateReferent dr, java.time.LocalDateTime now, com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> from, com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> to, int tense) {
        if (dr.getPointer() == com.pullenti.ner.date.DatePointerType.TODAY) {
            from.value = now;
            to.value = now;
            return true;
        }
        if (!dr.isRelative() && dr.getDt() != null) {
            from.value = (to.value = dr.getDt());
            return true;
        }
        com.pullenti.ner.Token t = new com.pullenti.ner.Token(null, 0, 1);
        DateExToken det = new DateExToken(t, t);
        det.itemsFrom = _createDateEx(dr);
        boolean inoutres917 = det.getDates(now, from, to, tense);
        return inoutres917;
    }

    public static boolean calculateDateRange2(com.pullenti.ner.date.DateRangeReferent dr, java.time.LocalDateTime now, com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> from, com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> to, int tense) {
        from.value = java.time.LocalDateTime.MIN;
        to.value = java.time.LocalDateTime.MAX;
        java.time.LocalDateTime dt0;
        java.time.LocalDateTime dt1;
        if (dr.getDateFrom() == null) {
            if (dr.getDateTo() == null) 
                return false;
            com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> wrapdt0918 = new com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime>();
            com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> wrapdt1919 = new com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime>();
            boolean inoutres920 = calculateDateRange(dr.getDateTo(), now, wrapdt0918, wrapdt1919, tense);
            dt0 = wrapdt0918.value;
            dt1 = wrapdt1919.value;
            if (!inoutres920) 
                return false;
            to.value = dt1;
            return true;
        }
        else if (dr.getDateTo() == null) {
            com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> wrapdt0921 = new com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime>();
            com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> wrapdt1922 = new com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime>();
            boolean inoutres923 = calculateDateRange(dr.getDateFrom(), now, wrapdt0921, wrapdt1922, tense);
            dt0 = wrapdt0921.value;
            dt1 = wrapdt1922.value;
            if (!inoutres923) 
                return false;
            from.value = dt0;
            return true;
        }
        com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> wrapdt0927 = new com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime>();
        com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> wrapdt1928 = new com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime>();
        boolean inoutres929 = calculateDateRange(dr.getDateFrom(), now, wrapdt0927, wrapdt1928, tense);
        dt0 = wrapdt0927.value;
        dt1 = wrapdt1928.value;
        if (!inoutres929) 
            return false;
        from.value = dt0;
        java.time.LocalDateTime dt2;
        java.time.LocalDateTime dt3;
        com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> wrapdt2924 = new com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime>();
        com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> wrapdt3925 = new com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime>();
        boolean inoutres926 = calculateDateRange(dr.getDateTo(), now, wrapdt2924, wrapdt3925, tense);
        dt2 = wrapdt2924.value;
        dt3 = wrapdt3925.value;
        if (!inoutres926) 
            return false;
        to.value = dt3;
        return true;
    }

    public static void appendToString(com.pullenti.ner.date.DateReferent dr, StringBuilder res) {
        java.time.LocalDateTime dt0;
        java.time.LocalDateTime dt1;
        java.time.LocalDateTime cur = (com.pullenti.ner.ProcessorService.DEBUGCURRENTDATETIME == null ? java.time.LocalDateTime.now() : com.pullenti.ner.ProcessorService.DEBUGCURRENTDATETIME);
        com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> wrapdt0930 = new com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime>();
        com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> wrapdt1931 = new com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime>();
        boolean inoutres932 = DateRelHelper.calculateDateRange(dr, cur, wrapdt0930, wrapdt1931, 0);
        dt0 = wrapdt0930.value;
        dt1 = wrapdt1931.value;
        if (!inoutres932) 
            return;
        _appendDates(cur, dt0, dt1, res);
    }

    public static void appendToString2(com.pullenti.ner.date.DateRangeReferent dr, StringBuilder res) {
        java.time.LocalDateTime dt0;
        java.time.LocalDateTime dt1;
        java.time.LocalDateTime cur = (com.pullenti.ner.ProcessorService.DEBUGCURRENTDATETIME == null ? java.time.LocalDateTime.now() : com.pullenti.ner.ProcessorService.DEBUGCURRENTDATETIME);
        com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> wrapdt0933 = new com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime>();
        com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime> wrapdt1934 = new com.pullenti.unisharp.Outargwrapper<java.time.LocalDateTime>();
        boolean inoutres935 = DateRelHelper.calculateDateRange2(dr, cur, wrapdt0933, wrapdt1934, 0);
        dt0 = wrapdt0933.value;
        dt1 = wrapdt1934.value;
        if (!inoutres935) 
            return;
        _appendDates(cur, dt0, dt1, res);
    }

    private static void _appendDates(java.time.LocalDateTime cur, java.time.LocalDateTime dt0, java.time.LocalDateTime dt1, StringBuilder res) {
        int mon0 = dt0.getMonthValue();
        res.append(" (").append(dt0.getYear()).append(".").append(String.format("%02d", mon0)).append(".").append(String.format("%02d", dt0.getDayOfMonth()));
        if (dt0.getHour() > 0 || dt0.getMinute() > 0) 
            res.append(" ").append(String.format("%02d", dt0.getHour())).append(":").append(String.format("%02d", dt0.getMinute()));
        if (dt0.compareTo(dt1) != 0) {
            int mon1 = dt1.getMonthValue();
            res.append("-").append(dt1.getYear()).append(".").append(String.format("%02d", mon1)).append(".").append(String.format("%02d", dt1.getDayOfMonth()));
            if (dt1.getHour() > 0 || dt1.getMinute() > 0) 
                res.append(" ").append(String.format("%02d", dt1.getHour())).append(":").append(String.format("%02d", dt1.getMinute()));
        }
        int monc = cur.getMonthValue();
        res.append(" отн. ").append(cur.getYear()).append(".").append(String.format("%02d", monc)).append(".").append(String.format("%02d", cur.getDayOfMonth()));
        if (cur.getHour() > 0 || cur.getMinute() > 0) 
            res.append(" ").append(String.format("%02d", cur.getHour())).append(":").append(String.format("%02d", cur.getMinute()));
        res.append(")");
    }
    public DateRelHelper() {
    }
}
