B4J Question Need help creating a Persian calendar pop-up view...

MegatenFreak

Active Member
Licensed User
Hi everyone.
As the title clarifies, I've written a Windows app which contains a lot of forms where dates need to be given. Currently the date needs to be manual inserted, but I really need to make it easy and cool by adding one of those pop-up date choosing views. I was wondering if I should alter the calendar view in B4J or if is there a simpler way. I've read some stuff about it in these forums, but nothing really concrete.
I'd really appreciate any help. Thanks a lot in advance.
 

MicroDrie

Well-Known Member
Licensed User
A recent concrete example is: DatePicker and date format.
If it doesn't flt your requirements , post your code, and write out what is wrong, what you want to achieve, so that we can help you.
 
Upvote 0

MegatenFreak

Active Member
Licensed User
Thanks. I read that thread, but it focuses on how to format the date received by the picker into different formats. That'll be helpful once I receive the input from the visual datepickler.
However, the main problem in my case is to be able to edit the visual AND data aspects of the datepicker view. For example, I need to change the month names, number of days in each month, the range of years. In other words, I need to be able to directly edit the DatePicker code, whether it's in Basic or Java, so I can apply those changes.
It seems to be the only way.
But where can I find the code or stylesheet or anything of the B4J DatePicker so I can edit it? Is the source even accessible?
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
There is a lot possible, however all starts which program solution you use. I think that it is the most handy way that you write first a short program what you want to archive in English language. Based on that solution, we can see how we can help you to convert English to Persian language.
 
Upvote 0

MegatenFreak

Active Member
Licensed User
Thanks MicroDrie. If I can't access the current B4J DatePicker, I suppose I'll have to write my own datepicker view from scratch. I'll see what I can do.
Brian Dean, I'm not working with Android; and the calendar conversion itself is another difficult story! For now I'm trying to pull off the visual aspects of the view. Besides, the date conversion is not an issue! I've already done it, fortunately!
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
Edit: Maybe this post is a good starting point: [B4X] [XUI] AnotherDatePicker re-shufle the layout and combine it with this use this class:
B4X:
'    --- This class needs JavaObject (tested with version 2.06)
'    ---
Sub Class_Globals

End Sub

'Initializes the object. You can add parameters to this method if needed.
'    --- See https://www.b4x.com/android/forum/threads/calling-java-class.103718/post-650373
Public Sub Initialize
    Dim jo As JavaObject = Me
   
'    Note#1: The class string For InitializeNewInstance Is composed of
'         1) Package name: in this test Case b4j.example
'         2) The name of the class module in B4A in lowercase. In this Case the class module
'            name Is PersianCalendar, but since B4A lowercases module names it becomes: persiancalendar
'         3) The name of the class defined in the #if JAVA section (case sensitive): JalaliCalendar
'    Note#2: You could have a constructor declared. The call here would call one with
'            no parameters
   
    jo.InitializeNewInstance("b4j.example.persiancalendar.JalaliCalendar", Array(Null))
    Log(jo.RunMethod("ReturnString", Array("Hello from class in class JalaliCalendar")))

'    --- Set date once
    Log(jo.RunMethod("GregorianDateToJalali", Array(1371, 8, 3)))
   
End Sub


#IF JAVA
/* source: https://github.com/razeghi71/JalaliCalendar/blob/master/src/main/java/ir/huri/jcal/JalaliCalendar.java */

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class JalaliCalendar {

    private int year, month, day;
   
   
//  It is not necessary to declare a constructor, but one could. If you have
//  parameters you would need to change the Array(Null) section of the above
//  call to InitializeNewInstance method.

//  Here we test the class
    public String ReturnString( String Value )
    {
        return Value;
    }

    public String GregorianDateToJalali(int yearv, int monthv, int dayv )
    {
//        --- First we set the Persian date
        JalaliCalendar myRoomMateBirthday = new JalaliCalendar(yearv, monthv, dayv);

//        --- And we read back the date and the day name
        return myRoomMateBirthday.toString() + " = " + getDayOfWeek() +
            " day of the week = " + myRoomMateBirthday.getDayOfWeekString();
    }
   

    /**
     * Today Jalali Date
     */
    public JalaliCalendar() {
        fromGregorian(new GregorianCalendar());
    }

    /**
     * Create a ir.huri.jcal.JalaliCalendar object
     * @param year Jalali Year
     * @param month Jalali Month
     * @param day Jalali Day
     */
    public JalaliCalendar(int year, int month, int day) {
        set(year, month, day);
    }


    /**
     * Create a ir.huri.jcal.JalaliCalendar object from gregorian calendar
     * @param gc gregorian calendar object
     */
    public JalaliCalendar(GregorianCalendar gc){
        fromGregorian(gc);
    }


    /**
     * Create a ir.huri.jcal.JalaliCalendar object from Localdate(java 8)
     * @param ld local date object
     */
    public JalaliCalendar(LocalDate ld) {
        fromGregorian(GregorianCalendar.from(ld.atStartOfDay(ZoneId.systemDefault())));
    }


    /**
     * Create a ir.huri.jcal.JalaliCalendar object from Date object
     * @param date Date object
     */
    public JalaliCalendar(Date date) {
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTime(date);
        fromGregorian(gc);
    }

    /**
     * Convert current jalali date to gregorian date
     * @return date converted gregorianDate
     */
    public GregorianCalendar toGregorian() {
        int julianDay = toJulianDay();
        return julianDayToGregorianCalendar(julianDay);
    }

    /**
     * set date from gregorian date
     * @param gc input gregorian calendar
     */
    public void fromGregorian(GregorianCalendar gc){
        int jd = gregorianToJulianDayNumber(gc);
        fromJulianDay(jd);
    }

    /**
     * @return yesterday date
     */
    public JalaliCalendar getYesterday() {
        return getDateByDiff(-1);
    }

    /**
     * @return tomorrow date
     */
    public JalaliCalendar getTomorrow() {
        return getDateByDiff(1);
    }

    /**
     * get Jalali date by day difference
     * @param diff number of day diffrents
     * @return jalali calendar diffحزن
     */
    public JalaliCalendar getDateByDiff(int diff) {
        GregorianCalendar gc = toGregorian();
        gc.add(Calendar.DAY_OF_MONTH, diff);
        return new JalaliCalendar(gc);
    }

    /**
     * @return day Of Week
     */
    public int getDayOfWeek() {
        return toGregorian().get(Calendar.DAY_OF_WEEK);
    }

    /**
     * @return get first day of week
     */
    public int getFirstDayOfWeek() {
        return toGregorian().getFirstDayOfWeek();
    }

    /**
     *
     * @return day name
     */
    public String getDayOfWeekString() {
        switch (getDayOfWeek()) {
            case 1:
                return "یک‌شنبه";
            case 2 :
                return "دوشنبه";
            case 3:
                return "سه‌شنبه";
            case 4:
                return "چهارشنبه";
            case 5:
                return "پنجشنبه";
            case 6:
                return "جمعه";
            case 7:
                return "شنبه";
            default:
                return "نامعلوم";
        }
    }

    /**
     *
     * @return month name
     */
    public String getMonthString() {
        switch (getMonth()) {
            case 1:
                return "فروردین";
            case 2 :
                return "اردیبهشت";
            case 3:
                return "خرداد";
            case 4:
                return "تیر";
            case 5:
                return "مرداد";
            case 6:
                return "شهریور";
            case 7:
                return "مهر";
            case 8:
                return "آبان";
            case 9:
                return "آذر";
            case 10:
                return "دی";
            case 11:
                return "بهمن";
            case 12:
                return "اسفند";
            default:
                return "نامعلوم";
        }
    }


    /**
     * get String with the following format :
     *  یکشنبه ۱۲ آبان
     * @return String format
     */

    public String getDayOfWeekDayMonthString() {
        return getDayOfWeekString() + " " + getDay() + " " + getMonthString() ;
    }

    /**
     *
     * @return return whether this year is a jalali leap year
     */
    public boolean isLeap() {
        return  getLeapFactor(getYear()) == 0;
    }

    public int getYearLength() {
        return  isLeap() ? 366 : 365;
    }

    public int getMonthLength() {
        if ( getMonth() < 7 ) {
            return 31;
        } else if ( getMonth() < 12 ) {
            return 30;
        } else if ( getMonth() == 12 ) {
            if (isLeap())
                return 30;
            else
                return 29;
        }
        return 0;
    }

    public int getDay() {
        return day;
    }

    public int getMonth() {
        return month;
    }

    public int getYear() {
        return year;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public void setDay(int day) {
        this.day = day;
    }

    public void set(int year, int month, int day) {
        setYear(year);
        setMonth(month);
        setDay(day);
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        JalaliCalendar that = (JalaliCalendar) o;

        return year == that.year && month == that.month && day == that.day;
    }

    private int gregorianToJulianDayNumber(GregorianCalendar gc) {
        int gregorianYear = gc.get(GregorianCalendar.YEAR);
        int gregorianMonth = gc.get(GregorianCalendar.MONTH) + 1;
        int gregorianDay = gc.get(GregorianCalendar.DAY_OF_MONTH);

        return  (((1461 * (gregorianYear + 4800 + (gregorianMonth - 14) / 12)) / 4
                + (367 * (gregorianMonth - 2 - 12 * ((gregorianMonth - 14) / 12))) / 12
                - (3 * ((gregorianYear + 4900 + (gregorianMonth - 14) / 12) / 100)) / 4 + gregorianDay
                - 32075) - (gregorianYear + 100100 + (gregorianMonth - 8) / 6) / 100 * 3 / 4 + 752);
    }

    private int julianToJulianDayNumber(JulianCalendar jc) {
        int julianYear = jc.getYear();
        int julianMonth = jc.getMonth();
        int JulianDay = jc.getDay();

        return (1461 * (julianYear + 4800 + (julianMonth - 14) / 12)) / 4
                + (367 * (julianMonth - 2 - 12 * ((julianMonth - 14) / 12))) / 12
                - (3 * ((julianYear + 4900 + (julianMonth - 14) / 12) / 100)) / 4 + JulianDay
                - 32075;
    }

    private GregorianCalendar julianDayToGregorianCalendar(int JulianDayNumber) {

        int j = 4 * JulianDayNumber + 139361631 + (4 * JulianDayNumber + 183187720) / 146097 * 3 / 4 * 4 - 3908;
        int i = (j % 1461) / 4 * 5 + 308;

        int gregorianDay = (i % 153) / 5 + 1;
        int gregorianMonth = ((i / 153) % 12) + 1;
        int gregorianYear = j / 1461 - 100100 + (8 - gregorianMonth) / 6;

        return new GregorianCalendar(gregorianYear, gregorianMonth - 1, gregorianDay);
    }

    private void fromJulianDay(int JulianDayNumber) {
        GregorianCalendar gc = julianDayToGregorianCalendar(JulianDayNumber);
        int gregorianYear = gc.get(GregorianCalendar.YEAR);

        int jalaliYear, jalaliMonth, jalaliDay;

        jalaliYear = gregorianYear - 621;

        GregorianCalendar gregorianFirstFarvardin = new JalaliCalendar(jalaliYear, 1, 1).getGregorianFirstFarvardin();
        int JulianDayFarvardinFirst = gregorianToJulianDayNumber(gregorianFirstFarvardin);
        int diffFromFarvardinFirst = JulianDayNumber - JulianDayFarvardinFirst;



        if (diffFromFarvardinFirst >= 0) {
            if (diffFromFarvardinFirst <= 185) {
                jalaliMonth = 1 + diffFromFarvardinFirst / 31;
                jalaliDay = (diffFromFarvardinFirst % 31) + 1;
                set(jalaliYear, jalaliMonth, jalaliDay);
                return;
            } else {
                diffFromFarvardinFirst = diffFromFarvardinFirst - 186;
            }
        } else {
            diffFromFarvardinFirst = diffFromFarvardinFirst + 179;
            if (getLeapFactor(jalaliYear) == 1)
                    diffFromFarvardinFirst = diffFromFarvardinFirst + 1;
            jalaliYear -= 1;
        }


        jalaliMonth = 7 + diffFromFarvardinFirst / 30;
        jalaliDay = (diffFromFarvardinFirst % 30) + 1;
        set(jalaliYear, jalaliMonth, jalaliDay);
    }

    private int toJulianDay() {
        int jalaliMonth = getMonth();
        int jalaliDay = getDay();

        GregorianCalendar gregorianFirstFarvardin = getGregorianFirstFarvardin();
        int gregorianYear = gregorianFirstFarvardin.get(Calendar.YEAR);
        int gregorianMonth = gregorianFirstFarvardin.get(Calendar.MONTH) + 1;
        int gregorianDay = gregorianFirstFarvardin.get(Calendar.DAY_OF_MONTH);

        JulianCalendar julianFirstFarvardin = new JulianCalendar(gregorianYear, gregorianMonth, gregorianDay) ;


        int julianDay = julianToJulianDayNumber(julianFirstFarvardin) + (jalaliMonth - 1) * 31 - jalaliMonth / 7 * (jalaliMonth - 7)
                + jalaliDay - 1;

        return julianDay;
    }


    private GregorianCalendar getGregorianFirstFarvardin() {
        int marchDay = 0;
        int[] breaks = { -61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210,
                1635, 2060, 2097, 2192, 2262, 2324, 2394, 2456, 3178 };

        int jalaliYear = getYear();
        int gregorianYear = jalaliYear + 621;
        int jalaliLeap = -14;
        int jp = breaks[0];

        int jump = 0;
        for (int j = 1; j <= 19; j++) {
            int jm = breaks[j];
            jump = jm - jp;
            if (jalaliYear < jm) {
                int N = jalaliYear - jp;
                jalaliLeap = jalaliLeap + N / 33 * 8 + (N % 33 + 3) / 4;

                if ((jump % 33) == 4 && (jump - N) == 4)
                    jalaliLeap = jalaliLeap + 1;

                int GregorianLeap = (gregorianYear / 4) - (gregorianYear / 100 + 1) * 3 / 4 - 150;

                marchDay = 20 + (jalaliLeap - GregorianLeap);

                if ((jump - N) < 6)
                    N = N - jump + (jump + 4) / 33 * 33;

                break;
            }

            jalaliLeap = jalaliLeap + jump / 33 * 8 + (jump % 33) / 4;
            jp = jm;
        }

        return new GregorianCalendar(gregorianYear, 2, marchDay);
    }

    private int getLeapFactor(int jalaliYear) {
        int leap = 0;
        int[] breaks = { -61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210,
                1635, 2060, 2097, 2192, 2262, 2324, 2394, 2456, 3178 };

        int jp = breaks[0];

        int jump = 0;
        for (int j = 1; j <= 19; j++) {
            int jm = breaks[j];
            jump = jm - jp;
            if (jalaliYear < jm) {
                int N = jalaliYear - jp;

                if ((jump - N) < 6)
                    N = N - jump + (jump + 4) / 33 * 33;

                leap = ((((N + 1) % 33) - 1) % 4);

                if (leap == -1)
                    leap = 4;

                break;
            }

            jp = jm;
        }

        return leap;
    }

    @Override
    public String toString() {
        return String.format("%04d-%02d-%02d", getYear(), getMonth(), getDay());
    }


    private class JulianCalendar {
        int year;
        int month;
        int day;

        public JulianCalendar(int year, int month, int day) {
            this.year = year;
            this.month = month;
            this.day = day;
        }

        public int getYear() {
            return year;
        }
        public int getMonth() {
            return month;
        }
        public int getDay() {
            return day;
        }
    }
}
#End If
 
Last edited:
Upvote 0

MegatenFreak

Active Member
Licensed User
Edit: Maybe this post is a good starting point: [B4X] [XUI] AnotherDatePicker re-shufle the layout and combine it with this use this class:
B4X:
'    --- This class needs JavaObject (tested with version 2.06)
'    ---
Sub Class_Globals

End Sub

'Initializes the object. You can add parameters to this method if needed.
'    --- See https://www.b4x.com/android/forum/threads/calling-java-class.103718/post-650373
Public Sub Initialize
    Dim jo As JavaObject = Me
  
'    Note#1: The class string For InitializeNewInstance Is composed of
'         1) Package name: in this test Case b4j.example
'         2) The name of the class module in B4A in lowercase. In this Case the class module
'            name Is PersianCalendar, but since B4A lowercases module names it becomes: persiancalendar
'         3) The name of the class defined in the #if JAVA section (case sensitive): JalaliCalendar
'    Note#2: You could have a constructor declared. The call here would call one with
'            no parameters
  
    jo.InitializeNewInstance("b4j.example.persiancalendar.JalaliCalendar", Array(Null))
    Log(jo.RunMethod("ReturnString", Array("Hello from class in class JalaliCalendar")))

'    --- Set date once
    Log(jo.RunMethod("GregorianDateToJalali", Array(1371, 8, 3)))
  
End Sub


#IF JAVA
/* source: https://github.com/razeghi71/JalaliCalendar/blob/master/src/main/java/ir/huri/jcal/JalaliCalendar.java */

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class JalaliCalendar {

    private int year, month, day;
  
  
//  It is not necessary to declare a constructor, but one could. If you have
//  parameters you would need to change the Array(Null) section of the above
//  call to InitializeNewInstance method.

//  Here we test the class
    public String ReturnString( String Value )
    {
        return Value;
    }

    public String GregorianDateToJalali(int yearv, int monthv, int dayv )
    {
//        --- First we set the Persian date
        JalaliCalendar myRoomMateBirthday = new JalaliCalendar(yearv, monthv, dayv);

//        --- And we read back the date and the day name
        return myRoomMateBirthday.toString() + " = " + getDayOfWeek() +
            " day of the week = " + myRoomMateBirthday.getDayOfWeekString();
    }
  

    /**
     * Today Jalali Date
     */
    public JalaliCalendar() {
        fromGregorian(new GregorianCalendar());
    }

    /**
     * Create a ir.huri.jcal.JalaliCalendar object
     * @param year Jalali Year
     * @param month Jalali Month
     * @param day Jalali Day
     */
    public JalaliCalendar(int year, int month, int day) {
        set(year, month, day);
    }


    /**
     * Create a ir.huri.jcal.JalaliCalendar object from gregorian calendar
     * @param gc gregorian calendar object
     */
    public JalaliCalendar(GregorianCalendar gc){
        fromGregorian(gc);
    }


    /**
     * Create a ir.huri.jcal.JalaliCalendar object from Localdate(java 8)
     * @param ld local date object
     */
    public JalaliCalendar(LocalDate ld) {
        fromGregorian(GregorianCalendar.from(ld.atStartOfDay(ZoneId.systemDefault())));
    }


    /**
     * Create a ir.huri.jcal.JalaliCalendar object from Date object
     * @param date Date object
     */
    public JalaliCalendar(Date date) {
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTime(date);
        fromGregorian(gc);
    }

    /**
     * Convert current jalali date to gregorian date
     * @return date converted gregorianDate
     */
    public GregorianCalendar toGregorian() {
        int julianDay = toJulianDay();
        return julianDayToGregorianCalendar(julianDay);
    }

    /**
     * set date from gregorian date
     * @param gc input gregorian calendar
     */
    public void fromGregorian(GregorianCalendar gc){
        int jd = gregorianToJulianDayNumber(gc);
        fromJulianDay(jd);
    }

    /**
     * @return yesterday date
     */
    public JalaliCalendar getYesterday() {
        return getDateByDiff(-1);
    }

    /**
     * @return tomorrow date
     */
    public JalaliCalendar getTomorrow() {
        return getDateByDiff(1);
    }

    /**
     * get Jalali date by day difference
     * @param diff number of day diffrents
     * @return jalali calendar diffحزن
     */
    public JalaliCalendar getDateByDiff(int diff) {
        GregorianCalendar gc = toGregorian();
        gc.add(Calendar.DAY_OF_MONTH, diff);
        return new JalaliCalendar(gc);
    }

    /**
     * @return day Of Week
     */
    public int getDayOfWeek() {
        return toGregorian().get(Calendar.DAY_OF_WEEK);
    }

    /**
     * @return get first day of week
     */
    public int getFirstDayOfWeek() {
        return toGregorian().getFirstDayOfWeek();
    }

    /**
     *
     * @return day name
     */
    public String getDayOfWeekString() {
        switch (getDayOfWeek()) {
            case 1:
                return "یک‌شنبه";
            case 2 :
                return "دوشنبه";
            case 3:
                return "سه‌شنبه";
            case 4:
                return "چهارشنبه";
            case 5:
                return "پنجشنبه";
            case 6:
                return "جمعه";
            case 7:
                return "شنبه";
            default:
                return "نامعلوم";
        }
    }

    /**
     *
     * @return month name
     */
    public String getMonthString() {
        switch (getMonth()) {
            case 1:
                return "فروردین";
            case 2 :
                return "اردیبهشت";
            case 3:
                return "خرداد";
            case 4:
                return "تیر";
            case 5:
                return "مرداد";
            case 6:
                return "شهریور";
            case 7:
                return "مهر";
            case 8:
                return "آبان";
            case 9:
                return "آذر";
            case 10:
                return "دی";
            case 11:
                return "بهمن";
            case 12:
                return "اسفند";
            default:
                return "نامعلوم";
        }
    }


    /**
     * get String with the following format :
     *  یکشنبه ۱۲ آبان
     * @return String format
     */

    public String getDayOfWeekDayMonthString() {
        return getDayOfWeekString() + " " + getDay() + " " + getMonthString() ;
    }

    /**
     *
     * @return return whether this year is a jalali leap year
     */
    public boolean isLeap() {
        return  getLeapFactor(getYear()) == 0;
    }

    public int getYearLength() {
        return  isLeap() ? 366 : 365;
    }

    public int getMonthLength() {
        if ( getMonth() < 7 ) {
            return 31;
        } else if ( getMonth() < 12 ) {
            return 30;
        } else if ( getMonth() == 12 ) {
            if (isLeap())
                return 30;
            else
                return 29;
        }
        return 0;
    }

    public int getDay() {
        return day;
    }

    public int getMonth() {
        return month;
    }

    public int getYear() {
        return year;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public void setDay(int day) {
        this.day = day;
    }

    public void set(int year, int month, int day) {
        setYear(year);
        setMonth(month);
        setDay(day);
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        JalaliCalendar that = (JalaliCalendar) o;

        return year == that.year && month == that.month && day == that.day;
    }

    private int gregorianToJulianDayNumber(GregorianCalendar gc) {
        int gregorianYear = gc.get(GregorianCalendar.YEAR);
        int gregorianMonth = gc.get(GregorianCalendar.MONTH) + 1;
        int gregorianDay = gc.get(GregorianCalendar.DAY_OF_MONTH);

        return  (((1461 * (gregorianYear + 4800 + (gregorianMonth - 14) / 12)) / 4
                + (367 * (gregorianMonth - 2 - 12 * ((gregorianMonth - 14) / 12))) / 12
                - (3 * ((gregorianYear + 4900 + (gregorianMonth - 14) / 12) / 100)) / 4 + gregorianDay
                - 32075) - (gregorianYear + 100100 + (gregorianMonth - 8) / 6) / 100 * 3 / 4 + 752);
    }

    private int julianToJulianDayNumber(JulianCalendar jc) {
        int julianYear = jc.getYear();
        int julianMonth = jc.getMonth();
        int JulianDay = jc.getDay();

        return (1461 * (julianYear + 4800 + (julianMonth - 14) / 12)) / 4
                + (367 * (julianMonth - 2 - 12 * ((julianMonth - 14) / 12))) / 12
                - (3 * ((julianYear + 4900 + (julianMonth - 14) / 12) / 100)) / 4 + JulianDay
                - 32075;
    }

    private GregorianCalendar julianDayToGregorianCalendar(int JulianDayNumber) {

        int j = 4 * JulianDayNumber + 139361631 + (4 * JulianDayNumber + 183187720) / 146097 * 3 / 4 * 4 - 3908;
        int i = (j % 1461) / 4 * 5 + 308;

        int gregorianDay = (i % 153) / 5 + 1;
        int gregorianMonth = ((i / 153) % 12) + 1;
        int gregorianYear = j / 1461 - 100100 + (8 - gregorianMonth) / 6;

        return new GregorianCalendar(gregorianYear, gregorianMonth - 1, gregorianDay);
    }

    private void fromJulianDay(int JulianDayNumber) {
        GregorianCalendar gc = julianDayToGregorianCalendar(JulianDayNumber);
        int gregorianYear = gc.get(GregorianCalendar.YEAR);

        int jalaliYear, jalaliMonth, jalaliDay;

        jalaliYear = gregorianYear - 621;

        GregorianCalendar gregorianFirstFarvardin = new JalaliCalendar(jalaliYear, 1, 1).getGregorianFirstFarvardin();
        int JulianDayFarvardinFirst = gregorianToJulianDayNumber(gregorianFirstFarvardin);
        int diffFromFarvardinFirst = JulianDayNumber - JulianDayFarvardinFirst;



        if (diffFromFarvardinFirst >= 0) {
            if (diffFromFarvardinFirst <= 185) {
                jalaliMonth = 1 + diffFromFarvardinFirst / 31;
                jalaliDay = (diffFromFarvardinFirst % 31) + 1;
                set(jalaliYear, jalaliMonth, jalaliDay);
                return;
            } else {
                diffFromFarvardinFirst = diffFromFarvardinFirst - 186;
            }
        } else {
            diffFromFarvardinFirst = diffFromFarvardinFirst + 179;
            if (getLeapFactor(jalaliYear) == 1)
                    diffFromFarvardinFirst = diffFromFarvardinFirst + 1;
            jalaliYear -= 1;
        }


        jalaliMonth = 7 + diffFromFarvardinFirst / 30;
        jalaliDay = (diffFromFarvardinFirst % 30) + 1;
        set(jalaliYear, jalaliMonth, jalaliDay);
    }

    private int toJulianDay() {
        int jalaliMonth = getMonth();
        int jalaliDay = getDay();

        GregorianCalendar gregorianFirstFarvardin = getGregorianFirstFarvardin();
        int gregorianYear = gregorianFirstFarvardin.get(Calendar.YEAR);
        int gregorianMonth = gregorianFirstFarvardin.get(Calendar.MONTH) + 1;
        int gregorianDay = gregorianFirstFarvardin.get(Calendar.DAY_OF_MONTH);

        JulianCalendar julianFirstFarvardin = new JulianCalendar(gregorianYear, gregorianMonth, gregorianDay) ;


        int julianDay = julianToJulianDayNumber(julianFirstFarvardin) + (jalaliMonth - 1) * 31 - jalaliMonth / 7 * (jalaliMonth - 7)
                + jalaliDay - 1;

        return julianDay;
    }


    private GregorianCalendar getGregorianFirstFarvardin() {
        int marchDay = 0;
        int[] breaks = { -61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210,
                1635, 2060, 2097, 2192, 2262, 2324, 2394, 2456, 3178 };

        int jalaliYear = getYear();
        int gregorianYear = jalaliYear + 621;
        int jalaliLeap = -14;
        int jp = breaks[0];

        int jump = 0;
        for (int j = 1; j <= 19; j++) {
            int jm = breaks[j];
            jump = jm - jp;
            if (jalaliYear < jm) {
                int N = jalaliYear - jp;
                jalaliLeap = jalaliLeap + N / 33 * 8 + (N % 33 + 3) / 4;

                if ((jump % 33) == 4 && (jump - N) == 4)
                    jalaliLeap = jalaliLeap + 1;

                int GregorianLeap = (gregorianYear / 4) - (gregorianYear / 100 + 1) * 3 / 4 - 150;

                marchDay = 20 + (jalaliLeap - GregorianLeap);

                if ((jump - N) < 6)
                    N = N - jump + (jump + 4) / 33 * 33;

                break;
            }

            jalaliLeap = jalaliLeap + jump / 33 * 8 + (jump % 33) / 4;
            jp = jm;
        }

        return new GregorianCalendar(gregorianYear, 2, marchDay);
    }

    private int getLeapFactor(int jalaliYear) {
        int leap = 0;
        int[] breaks = { -61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210,
                1635, 2060, 2097, 2192, 2262, 2324, 2394, 2456, 3178 };

        int jp = breaks[0];

        int jump = 0;
        for (int j = 1; j <= 19; j++) {
            int jm = breaks[j];
            jump = jm - jp;
            if (jalaliYear < jm) {
                int N = jalaliYear - jp;

                if ((jump - N) < 6)
                    N = N - jump + (jump + 4) / 33 * 33;

                leap = ((((N + 1) % 33) - 1) % 4);

                if (leap == -1)
                    leap = 4;

                break;
            }

            jp = jm;
        }

        return leap;
    }

    @Override
    public String toString() {
        return String.format("%04d-%02d-%02d", getYear(), getMonth(), getDay());
    }


    private class JulianCalendar {
        int year;
        int month;
        int day;

        public JulianCalendar(int year, int month, int day) {
            this.year = year;
            this.month = month;
            this.day = day;
        }

        public int getYear() {
            return year;
        }
        public int getMonth() {
            return month;
        }
        public int getDay() {
            return day;
        }
    }
}
#End If

OMG! These are gonna be super helpful!
Thank you ever so much Micro3;)
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
OMG! These are gonna be super helpful!
You may understand that I do not know the Persian language and unfortunately I am not familiar with the calendar. The class is fairly well documented. I have included an interface example. Especially if you are not a Java expert like me, I would choose for a 1000 small steps approach, instead of 1 big step with a lot of changes at once. It can also be useful to occasionally add some loging temporarily because Inline - Java debugging is difficult which on line the error is when when everything is almost the same.
B4X:
System.out.printf("Loging text");
or
B4X:
BA.Log("Loging text");

The advantage of the AnotherDatePicker is that you can also adapt the western layout to the Persian format. Good luck, I am very curious about the result.
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
Mmm.🤔 I saw that also. I must then wish you the best of luck 🙂
 
Upvote 0

MegatenFreak

Active Member
Licensed User
Hi. Just thought I'd provide an update. It suddenly occurred to me it might be fun to write my own datepicker view from scratch (independent from the default B4J views or B4XView), you know, put it all together with panes and labels and choice boxes! It was easier than I expected, and I did it! The main challenge was calculating on which day of the week each month begins and stuff like that.
I'll soon post it in the forum.
 
Upvote 0
Top