[JAVA] Trial and error to display national holidays in Android app development. Part 2

Thanks! This is Yosuke. I can't think of a good title w It's difficult to have a concise, concrete and nice title (laughs). I think it's a little different from blogging, and like me and the content, I'll do my best to make it feel good!

Part 1 explained the dates of national holidays. In the second part, I will introduce the way of thinking when assembling the source code (although I show that I thought this way ...), the source code, and some drawbacks, so I will introduce them as well. I will. As a review of the first part, I will repost the holiday days and remarks.

Holiday name date Remarks
New Year's Day January 1 -
Coming of age day 2nd Monday of January -
Foundation Day February 11 -
The emperor's birthday February 23 -
Vernal Equinox Day One of the 19th to 22nd of March Determine the date by the remainder of dividing the year by 4
Showa Day April 29 -
Constitution Memorial Day May 3 -
Greenery day May 4th -
Children's day May 5th -
Marine day 3rd Monday of July July 23, 2020
Mountain day August 11 August 10, 2020
Respect for the aged day 3rd Monday of September -
Autumnal Equinox Day One of the 22nd to 24th of September Determine the date by the remainder of dividing the year by 4
Sports day 2nd monday in october July 24, 2020
Culture Day November 3rd -
Labor Thanksgiving Day November 23 -

--Thinking

Way of thinking

Before I write the source code, I will explain my thoughts. The first one to use is the ** Calendar class **. By doing this, you can get the year, month, day, day of the week, and week, and set holidays accordingly .... That's natural (laughs). I use the database because I want to display holidays underlined in TextView and tap to see details in a dialog.

id name detail adress
1 New Year's Day One year... https....
2 Coming of age day On holidays... https...
... ... ... ...
15 Culture Day Emperor Meiji... https...
16 Labor Thanksgiving Day In the Reiwa era... https....

I omitted it in the middle, but assign an id to each holiday and display the holiday and its details based on that id ... Hmm holiday.PNG ↑ Do you understand like this ... Sorry for the poor explanation m (..) m Next is the transfer holiday, but this is also a database with only id and flag

id flag
100 0

If a holiday comes on Sunday, set the flag to 1 and return it to 0 if that day is a transfer holiday. I am doing something like that. That's why there are drawbacks ...

Source code

The source code is divided into Holiday.java, which determines national holidays, DateDatabeseHelper.java in the database, and MainActivity.java, which is the main database.

Holiday.java


public class Holiday {
    //Get today's date, day of the week, year, week
    int year,month,day,youbi,week;
    Calendar calendar = Calendar.getInstance();
    //Database
    DateDatabaseHelper helper = null;
    //Determine if you want to display national holidays
    boolean holidayFlag;
    //Get holiday names, details, and ids
    String holidayName,holidayDetail;
    int id;
    //Judge the transfer holiday
    boolean transHolidayFlag;


    public void holiday(){
        year = calendar.get(Calendar.YEAR); //Year
        month = calendar.get(Calendar.MONTH) + 1; //Month
        day = calendar.get(Calendar.DAY_OF_MONTH); //Day
        youbi = calendar.get(Calendar.DAY_OF_WEEK); //Day of the week
        week = calendar.get(Calendar.WEEK_OF_MONTH); //week
        if(month == 1 && day == 1){
            //New Year's Day
            id = 1;
            holidayFlag = true;
        }
        else if(month == 1 && week == 2 && youbi == 2){
            //Coming of age day
            id = 2;
            holidayFlag = true;
            }
        else if(month == 2 && day == 11){
            //Foundation Day
            id = 3;
            holidayFlag = true;
        }
        else if(month == 2 && day == 23){
            //The emperor's birthday
            id = 4;
            holidayFlag = true;
        }
        else if(month == 3){
            //Vernal Equinox Day
            switch (year % 4){
                case 0:
                    //1992-20 days until 2091
                    if(year >= 1992 && year <= 2091){
                        if(day == 20){
                            id = 5;
                            holidayFlag = true;
                        }
                        else {
                            holidayFlag = false;
                        }
                    }
                    //2092-19 days until 2099
                    else{
                        if(day == 19){
                            id = 5;
                            holidayFlag = true;
                        }
                        else {
                            holidayFlag = false;
                        }
                    }
                    break;
                case 1:
                    //1992-20 days until 2099
                    if(day == 20){
                        id = 5;
                        holidayFlag = true;
                    }
                    else {
                        holidayFlag = false;
                    }
                    break;
                case 2:
                    //1992-21 days until 2023
                    if(year >= 1992 && year <= 2023){
                        if(day == 21){
                            id = 5;
                            holidayFlag = true;
                        }
                        else{
                            holidayFlag = false;
                        }
                    }
                    //2024-20 days until 2099
                    else{
                        if(day == 20){
                            id = 5;
                            holidayFlag = true;
                        }
                        else{
                            holidayFlag = false;
                        }
                    }
                    break;
                case 3:
                    //1992-21 days until 2055
                    if(year >= 1992 && year <= 2055){
                        if(day == 21){
                            id = 5;
                            holidayFlag = true;
                        }
                        else{
                            holidayFlag = false;
                        }
                    }
                    //2056-20 days until 2099
                    else{
                        if(day == 20){
                            id = 5;
                            holidayFlag = true;
                        }
                        else{
                            holidayFlag = false;
                        }
                    }
                    break;
            }
        }
        else if(month == 4 && day == 29){
            //Showa Day
            id = 6;
            holidayFlag = true;
        }
        else if(month == 5 && day == 3){
            //Constitution Memorial Day
            id = 7;
            holidayFlag = true;
        }
        else if(month == 5 && day == 4){
            //Greenery day
            id = 8;
            holidayFlag = true;
        }
        else if(month == 5 && day == 5){
            //Children's day
            id = 9;
            holidayFlag = true;
        }
        else if(year != 2020 && month == 7 && week == 3 && youbi == 2){
            //Marine day
            id = 10;
            holidayFlag = true;
        }
        else if(year == 2020 && month == 7 && day == 23){
            //Marine Day will move only in 2020
            id = 10;
            holidayFlag = true;
        }
        else if(year != 2020 && month == 8 && day == 11){
            //Mountain day
           id = 11;
           holidayFlag = true;
        }
        else if(year == 2020 && month == 8 && day == 10){
            //Mountain day moves only in 2020
            id = 11;
            holidayFlag = true;
        }
        else if(month == 9 && week == 3 && youbi == 2){
            //Respect for the aged day
            id = 12;
            holidayFlag = true;
        }
        else if(month == 9){
            //Autumnal Equinox Day
            switch (year % 4){
                case 0:
                    //2012-22 days until 2099
                    if(day == 22){
                        id = 13;
                        holidayFlag = true;
                    }
                    else {
                        holidayFlag = false;
                    }
                    break;
                case 1:
                    //2012-23 days until 2043
                    if(year >= 2012 && year <= 2043){
                        if(day == 23){
                            id = 13;
                            holidayFlag = true;
                        }
                        else{
                            holidayFlag = false;
                        }
                    }
                    //2044-22 days until 2099
                    else{
                        if(day == 22){
                            id = 13;
                            holidayFlag = true;
                        }
                        else{
                            holidayFlag = false;
                        }
                    }
                    break;
                case 2:
                    //2012-23 days until 2075
                    if(year >= 2012 && year <= 2075){
                        if(day == 23){
                            id = 13;
                            holidayFlag = true;
                        }
                        else{
                            holidayFlag = false;
                        }
                    }
                    //2076-22 days until 2099
                    else{
                        if(day == 22){
                            id = 13;
                            holidayFlag = true;
                        }
                        else{
                            holidayFlag = false;
                        }
                    }
                    break;
                case 3:
                    //2012-23 days until 2099
                    if(day == 23){
                        id = 13;
                        holidayFlag = true;
                    }
                    else{
                        holidayFlag = false;
                    }
                    break;
            }
        }
        else if(year != 2020 && month == 10 && week == 2 && youbi == 2){
            //Sports day
            id = 14;
            holidayFlag = true;
        }
        else if(year == 2020 && month == 7 && day == 24){
            //Sports Day will move only in 2020
            id = 14;
            holidayFlag = true;
        }
        else if(month == 11 && day == 3){
            //Culture Day
            id = 15;
            holidayFlag = true;
        }
        else if(month == 11 && day == 23){
            //Labor Thanksgiving Day
            id = 16;
            holidayFlag = true;
        }
        else{
            holidayFlag = false;
        }
        }
        //Pass the main whether it is a holiday or not
    public boolean getHoliday(){
        return holidayFlag;
    }
    //pass id to main
    public int holiday_info(){
       return id;
    }
    //Pass to main if there are holidays on Sunday
    public boolean getTransferHoliday(){
        //If it's a holiday and that day is Sunday
        if(holidayFlag == true && youbi == 1){
            transHolidayFlag = true;
        }
        else{
            transHolidayFlag = false;
        }
        return transHolidayFlag;
    }
}

Although it is redundant, basically, it is judged whether the day is a holiday and whether there is a holiday on Sunday, and the judgment result is passed to Main.

DateDatabaseHelper.java


public class DateDatabaseHelper extends SQLiteOpenHelper {
    static final private String DBNAME = "OneDayDiary.sqlite";
    static final private int VERSION = 16;

    public DateDatabaseHelper(Context context) {
        super(context, DBNAME, null, VERSION);
    }

    @Override
    public void onOpen(SQLiteDatabase db) {
        super.onOpen(db);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
----Omission-----
//Holiday database
        db.execSQL("CREATE TABLE holiday(" +
                "id INTEGER PRIMARY KEY, name TEXT, detail TEXT, adress TEXT)");
        int[] id_holiday = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
        String[] name_holiday = {
                "New Year's Day","Coming of age day","Foundation Day","The emperor's birthday","Vernal Equinox Day","Showa Day","Constitution Memorial Day","Greenery day","Children's day",
                "Marine day","Mountain day","Respect for the aged day","Autumnal Equinox Day","Sports day","Culture Day","Labor Thanksgiving Day"
        };
        String[] detail_holiday = {
                "It is a holiday at the beginning of the year, and the holiday law aims to "celebrate the beginning of the year."",
                        "According to the Holiday Law, coming-of-age ceremonies are held in various places on a day with the purpose of "celebrating a young man who is aware that he has grown up and is trying to survive himself."",
                        "It was established as a day to celebrate the founding of the country. The Holiday Law stipulates, "We will continue to establish the country and cultivate a love for the country."",
                        "The purpose of the holiday law is to "celebrate the birth of the emperor", and various events such as the Tencho Festival are held at the general public touring and Shinto shrines in various places.",
                        "The holiday law stipulates that "praise nature and care for living things," and it is said that the length of day and night is equal.",
                        "This day, which is the birthday of Emperor Showa, has been established as "Showa Day". The Holiday Law stipulates that "after the turbulent days, we look back on the Showa era, which was reconstructed, and think about the future of the country."",
                        "The Holiday Law stipulates that this day is "to commemorate the enforcement of the Constitution of Japan and to promote the growth of the country."",
                        "The origin of the name is "Greenery Day" because Emperor Showa loved nature. There were other opinions such as "Science Day". According to the Holiday Law, the purpose is to "get close to nature, appreciate its benefits, and nurture a rich heart."",
                        "The purpose of this day, which is the Tango no Sekku, is stipulated in the Holiday Law, "We value the human rights of children, strive for their happiness, and thank their mothers."",
                        "According to the Holidays Law, Marine Day aims to "thank you for the benefits of the sea and wish for the prosperity of Japan, a maritime nation."",
                        "This day was established in 2014 and was newly established in 2016. This is the first new holiday in 20 years since "Marine Day" in 1996. The purpose of the holiday law is to "give the opportunity to get to know the mountains and appreciate the benefits of the mountains."",
                        "The holiday law aims to "respect the old people who have been in society for many years and celebrate their longevity."",
                        "It is said that the daytime is shortened and the length of daytime and nighttime is the same. The purpose of the holiday law is to "respect ancestors and mourn the lost people."",
                        "From 2020, the name was changed from "Physical Education Day" to "Sports Day". In 2020, it will move on July 24th. The holiday law states that "sports should be used to maintain a healthy mind and body."",
                        "On this day, which is the birthday of Emperor Meiji, according to the Holiday Law, the purpose is to "love freedom and peace and promote culture."",
                        "In the Reiwa era, this day is the last holiday of the year. The purpose of the Holiday Law is to "work hard, celebrate production, and thank each other.""
        };
        String[] url_holiday = {
                "https://ja.wikipedia.org/wiki/%E5%85%83%E6%97%A5",
                        "https://ja.wikipedia.org/wiki/%E6%88%90%E4%BA%BA%E3%81%AE%E6%97%A5",
                        "https://ja.wikipedia.org/wiki/%E5%BB%BA%E5%9B%BD%E8%A8%98%E5%BF%B5%E3%81%AE%E6%97%A5",
                        "https://ja.wikipedia.org/wiki/%E5%A4%A9%E7%9A%87%E8%AA%95%E7%94%9F%E6%97%A5",
                        "https://ja.wikipedia.org/wiki/%E6%98%A5%E5%88%86%E3%81%AE%E6%97%A5",
                        "https://ja.wikipedia.org/wiki/%E6%98%AD%E5%92%8C%E3%81%AE%E6%97%A5",
                        "https://ja.wikipedia.org/wiki/%E6%86%B2%E6%B3%95%E8%A8%98%E5%BF%B5%E6%97%A5_(%E6%97%A5%E6%9C%AC)",
                        "https://ja.wikipedia.org/wiki/%E3%81%BF%E3%81%A9%E3%82%8A%E3%81%AE%E6%97%A5",
                        "https://ja.wikipedia.org/wiki/%E3%81%93%E3%81%A9%E3%82%82%E3%81%AE%E6%97%A5",
                        "https://ja.wikipedia.org/wiki/%E6%B5%B7%E3%81%AE%E6%97%A5",
                        "https://ja.wikipedia.org/wiki/%E5%B1%B1%E3%81%AE%E6%97%A5",
                        "https://ja.wikipedia.org/wiki/%E6%95%AC%E8%80%81%E3%81%AE%E6%97%A5",
                        "https://ja.wikipedia.org/wiki/%E7%A7%8B%E5%88%86%E3%81%AE%E6%97%A5",
                        "https://ja.wikipedia.org/wiki/%E4%BD%93%E8%82%B2%E3%81%AE%E6%97%A5",
                        "https://ja.wikipedia.org/wiki/%E6%96%87%E5%8C%96%E3%81%AE%E6%97%A5",
                        "https://ja.wikipedia.org/wiki/%E5%8B%A4%E5%8A%B4%E6%84%9F%E8%AC%9D%E3%81%AE%E6%97%A5"
        };
        db.beginTransaction();
        try{
            SQLiteStatement sql_holiday = db.compileStatement(
                    "INSERT INTO holiday(id, name, detail, adress) VALUES(?,?,?,?)");
            for(int i = 0; i < id_holiday.length; i++){
                sql_holiday.bindLong(1,id_holiday[i]);
                sql_holiday.bindString(2,name_holiday[i]);
                sql_holiday.bindString(3,detail_holiday[i]);
                sql_holiday.bindString(4,url_holiday[i]);
                sql_holiday.executeInsert();
            }
            db.setTransactionSuccessful();
        } catch (SQLException e){
            e.printStackTrace();
        } finally {
            db.endTransaction();
        }
        db.execSQL("CREATE TABLE transHoliday(" +
                "id INTEGER PRIMARY KEY, flag INTEGER)");
        db.execSQL("INSERT INTO transHoliday(" +
                "id, flag) VALUES(100,0)");

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int old_v, int new_v) {
        db.execSQL("DROP TABLE IF EXISTS holiday");
        db.execSQL("DROP TABLE IF EXISTS transHoliday");
        onCreate(db);

    }


}   

In the database, data on holidays and data for turning holidays on and off are prepared in advance. By the way, I think the reason why the URL is entered as data can be used on another screen. The URL includes not only this holiday but also Fukuoka information and the URL of the anniversary of the day.

MainActivity.java


public class MainActivity extends AppCompatActivity{
//Ready to display date and day of the week
    private TextView today;
    Calendar calendar = Calendar.getInstance();
    int year,month,day;

---Omission---

//National holidays
    private TextView holiday;
    String holidayName,holidayDetail; //Holiday name and details
    boolean holidayFlag,transHolidayFlag; //Whether there are holidays and transfer holidays
    int holidayId; //ID for searching in DB
    long transHoliday = 0; //Substitute holiday flag
    Holiday Hday = new Holiday(); //Holiday class

---Omission---

//Ready to connect to the database
    private DateDatabaseHelper helper = null;
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //Declaration of each widget

---Omission---

 holiday = findViewById(R.id.holiday);

---Omission---

//Get today's date
        year = calendar.get(calendar.YEAR);
        month = calendar.get(calendar.MONTH) + 1;
        day = calendar.get(calendar.DAY_OF_MONTH);

---Omission---

    //National holidays
        //run holiday method
        Hday.holiday();
        //Determining if there are holidays
        holidayFlag = Hday.getHoliday();
        //Get the presence or absence of a transfer holiday
        transHolidayFlag = Hday.getTransferHoliday();
        //Substitute holiday id
        String[] transHdayId = {"100"};
        //Update DB flag to 1 if transHolidayFlag is true

            SQLiteDatabase db_transUp1 = helper.getWritableDatabase();
            try{
                if(transHolidayFlag == true) {
                ContentValues cv_transUp1 = new ContentValues();
                cv_transUp1.put("flag",1);
                db_transUp1.update("transHoliday",cv_transUp1,"id = ?",transHdayId);
                }
                Cursor cursor_transUp1 = db_transUp1.rawQuery("select flag from transHoliday",null);
                cursor_transUp1.moveToFirst();
                transHoliday = cursor_transUp1.getLong(0);
            } finally {
                db_transUp1.close();
            }


        if(holidayFlag == true){
            //Get name and details if there are holidays
           holidayId = Hday.holiday_info();
            SQLiteDatabase db_holiday = helper.getWritableDatabase();
            try{
                Cursor cursor_holiday = db_holiday.query(
                        "holiday",
                        new String[] {"name","detail"},
                        "id = ?",
                        new String[] {"" + holidayId},
                        null,
                        null,
                        null
                );
                cursor_holiday.moveToFirst();
                holidayName = cursor_holiday.getString(0);
                holidayDetail = cursor_holiday.getString(1);
                //Underline holidayName
                SpannableString uHoliday = new SpannableString(holidayName);
                uHoliday.setSpan(new UnderlineSpan(),0,holidayName.length(),0);
                holiday.setText(uHoliday);
                //Make the day of the week red
                day_of_the_week.setTextColor(Color.RED);
            } finally {
                db_holiday.close();
            }
        }
        else if(transHoliday == 1 && holidayFlag == false ){
            //If the transfer holiday flag is true and the national holiday flag is also false, that day is a transfer holiday
            holiday.setText("Substitute holiday");
            holidayDetail = "Today is a transfer holiday";
            //Return the DB transfer holiday flag to 0
            SQLiteDatabase db_transUp2 = helper.getWritableDatabase();
            try{
                ContentValues cv_transUp2 = new ContentValues();
                cv_transUp2.put("flag",0);
                db_transUp2.update("transHoliday",cv_transUp2,"id = ?",transHdayId);
            } finally {
                db_transUp2.close();
            }
        }
        else{
            //Do not display if it is not a holiday
            holiday.setText("");
        }
        //Show details in dialog
        holiday.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                builder.setTitle(holidayName);
                builder.setMessage(holidayDetail);
                builder.setCancelable(false);
                builder.setPositiveButton("OK",
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {

                            }
                        });
                builder.create().show();
            }
        });

---Omission---

//onCreate is here
    }
}

In Main, holidays and transfer holidays are judged based on the holidayFlag and transHolidayFlag received from Holiday.java, and holidays are switched on and off from the database, and transfer holidays are switched on and off from the database. Since .setOnClickListener can also be used in TextView, tap the displayed holiday name to display the details in a dialog.

Execution result

Since February 23, 2020 (Sunday) is just the Emperor's Birthday, I tried playing with the date on my smartphone. holidayExp1.png When you tap the red letter "Emperor's Birthday" on the left .. holidayExp2.png And details can be displayed. (The blue "Emperor's Birthday" on the right must be another anniversary ...) And the next Monday is a transfer holiday, so I will try it on the 24th. transExp1.png The transfer holiday itself does not need to be displayed separately, so it is not underlined, but if you tap it for the time being transExp2.png In this way, "Today is a transfer holiday" is displayed.

Disadvantage

The definition of a transfer holiday was "If there is a holiday on Sunday, the next weekday will be a transfer holiday." We can judge national holidays because we know the numbers, but we decided that the transfer holidays are Sundays and holidays. The problem here is

  1. You cannot determine the flag of the transfer holiday unless you log in every day.
  2. When the transfer holiday is displayed, the flag is set to 0, so the transfer holiday will not be displayed when restarting.
  3. When a rare weekday is sandwiched between holidays, it is not possible to handle that day as a holiday Can be mentioned. I'm thinking a lot when I'm writing this article (laughs), but 1 and 2 are common phenomena that occur because the flag becomes 0 or 0. I can only check it on the day of the event, so it's not just the cause of my worries, but the flowers are in bloom (laughs). It seems to be solved and it is hard to come out ... Oh, please forgive pattern 3 ... (It took an hour just to scratch the flaws ...)

It should be working fine on holidays! Well, it's redundant (laughs). Well, for the time being, I will report again if I can solve the problem of the transfer holiday by proceeding as it is. gekimuzu ..

** Addendum ** I am posting a corrected version because the processing on the ○ th Monday was incorrect. →https://qiita.com/ysk75/items/278c52bf4052991eb99d

References

National Holidays: https://en.wikipedia.org/wiki/%E5%9B%BD%E6%B0%91%E3%81%AE%E7%A5%9D%E6%97%A5 Get information about the date and time: https://www.javadrive.jp/start/calendar/index2.html

Recommended Posts

Trial and error to display national holidays in Android app development. Part 2
Trial and error to display national holidays in Android application development. Part 1
Android app to select and display images from the gallery
How to implement one-line display of TextView in Android development
Introduction to Android App Development 1 Installing JDK and Android Studio for mac
Java to C and C to Java in Android Studio
How to display error messages in Japanese
[Android application development] How to display in full screen (notification bar hidden)
Riot (chat app) development (settings) in Android Studio
Android app: Try to summarize events and listeners
[In team development] Error when moving to another member's branch and doing rails s [Rails]
App development beginners tried to make an Android calculator app
Implementation policy to dynamically save and display Timezone in Rails
Error Treatment Techniques Hit in iOS App Development ~ Xcode Edition ~
Reasons to use Servlet and JSP separately in Java development
How to develop and register a Sota app in Java
[Android] Try to display the effect on the touched part of the screen, which is common in games.
iOS app development: Timer app (2. Timer display)
Android app personal development kickoff
Introduction to Android application development
ROS app development on Android
What Android development beginners did before releasing the app in 2 weeks
I tried to create a simple map app in Android Studio
What I have learned in Java (Part 1) Java development flow and overview
Source to display character array with numberPicker in Android studio (Java)
What to do if you get a DISPLAY error in gym.render ()
[Android] Convert Map to JSON using GSON in Kotlin and Java