0

Any idea how to turn my date, which is now a string into a timestamp for Cloud Firestore to use? I want to use the timestamp to sort my firestore entries, but I can't turn my date from a string into a timestamp.

I searched up and tried using SimpleDateFormat to turn the string into Date but not working...

String journalDate = sdf.format(jDate.getText().toString().trim();

public class ChkListJournal extends AppCompatActivity {

    private EditText jTitle, jDate, jWType, jBox;
    private Button button_Save;

    private FirebaseFirestore mFirestore;

    DatePickerDialog.OnDateSetListener setListener;

    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chk_list_journal);

        mFirestore = FirebaseFirestore.getInstance();

        jTitle = findViewById(R.id.jTitle);
        jDate = findViewById(R.id.jDate);
        jWType = findViewById(R.id.jWType);
        jBox = findViewById(R.id.jBox);
        button_Save = findViewById(R.id.button_Save);
        button_Save.setOnClickListener(onSave);

        Calendar calendar= Calendar.getInstance();
        final int year = calendar.get(Calendar.YEAR);
        final int month = calendar.get(Calendar.MONTH);
        final int day = calendar.get(Calendar.DAY_OF_MONTH);


        /*
        jDate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DatePickerDialog datePickerDialog = new DatePickerDialog(
                        ChkListJournal.this,android.R.style.Theme_Holo_Light_Dialog_MinWidth, setListener,year,month,day);
                datePickerDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
                datePickerDialog.show();
            }
        });
        */



        jDate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DatePickerDialog datePickerDialog = new DatePickerDialog(
                        ChkListJournal.this, new DatePickerDialog.OnDateSetListener() {
                    @Override
                    public void onDateSet(DatePicker view, int year, int month, int day) {
                        month = month+1;
                        String date = day+"/"+month+"/"+year;

                        jDate.setText(date);
                    }
                },year,month,day);
                datePickerDialog.show();

                InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
            }

        });


        setListener =  new DatePickerDialog.OnDateSetListener() {
            @Override
            public void onDateSet(DatePicker view, int year, int month, int day) {
                month = month + 1;
                String date = day+"/"+month+"/"+year;
                jDate.setText(date);
            }
        };

    }





    private View.OnClickListener onSave = new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            String journalTitle = jTitle.getText().toString();
            String journalDate = sdf.format(jDate.getText().toString().trim();
            String journalWType = jWType.getText().toString();
            String journalBox = jBox.getText().toString();

            Map<String, String> userMap = new HashMap<>();

            userMap.put("journalTitle", journalTitle);
            userMap.put("journalDate", journalDate);
            userMap.put("journalWType", journalWType);
            userMap.put("journalBox", journalBox);

            mFirestore.collection("Journal").add(userMap).addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
                @Override
                public void onSuccess(DocumentReference documentReference) {

                    Toast.makeText(ChkListJournal.this, "Journal Entry Added", Toast.LENGTH_LONG).show();
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {

                    String error = e.getMessage();

                    Toast.makeText(ChkListJournal.this, "Error : " + error, Toast.LENGTH_LONG).show();
                }
            });

        }
    };


}

Error Log

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.sp.miniproject, PID: 7118
    java.lang.RuntimeException: Could not deserialize object. Failed to convert value of type com.google.firebase.Timestamp to String (found in field 'journalDate')
        at com.google.firebase.firestore.util.CustomClassMapper.deserializeError(CustomClassMapper.java:563)
        at com.google.firebase.firestore.util.CustomClassMapper.convertString(CustomClassMapper.java:479)
        at com.google.firebase.firestore.util.CustomClassMapper.deserializeToClass(CustomClassMapper.java:228)
        at com.google.firebase.firestore.util.CustomClassMapper.deserializeToType(CustomClassMapper.java:189)
        at com.google.firebase.firestore.util.CustomClassMapper.access$300(CustomClassMapper.java:54)
        at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:770)
        at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:741)
        at com.google.firebase.firestore.util.CustomClassMapper.convertBean(CustomClassMapper.java:542)
        at com.google.firebase.firestore.util.CustomClassMapper.deserializeToClass(CustomClassMapper.java:253)
        at com.google.firebase.firestore.util.CustomClassMapper.convertToCustomClass(CustomClassMapper.java:100)
        at com.google.firebase.firestore.DocumentSnapshot.toObject(DocumentSnapshot.java:183)
        at com.google.firebase.firestore.QueryDocumentSnapshot.toObject(QueryDocumentSnapshot.java:116)
        at com.google.firebase.firestore.DocumentSnapshot.toObject(DocumentSnapshot.java:161)
        at com.google.firebase.firestore.QueryDocumentSnapshot.toObject(QueryDocumentSnapshot.java:97)
        at com.firebase.ui.firestore.ClassSnapshotParser.parseSnapshot(ClassSnapshotParser.java:23)
        at com.firebase.ui.firestore.ClassSnapshotParser.parseSnapshot(ClassSnapshotParser.java:12)
        at com.firebase.ui.common.BaseCachingSnapshotParser.parseSnapshot(BaseCachingSnapshotParser.java:36)
        at com.firebase.ui.common.BaseObservableSnapshotArray.get(BaseObservableSnapshotArray.java:52)
        at com.firebase.ui.firestore.FirestoreRecyclerAdapter.getItem(FirestoreRecyclerAdapter.java:86)
        at com.firebase.ui.firestore.FirestoreRecyclerAdapter.onBindViewHolder(FirestoreRecyclerAdapter.java:158)
        at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
        at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
        at androidx.recyclerview.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1897)
        at androidx.recyclerview.widget.RecyclerView$1.run(RecyclerView.java:414)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
        at android.view.Choreographer.doCallbacks(Choreographer.java:686)
        at android.view.Choreographer.doFrame(Choreographer.java:618)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
V/NativeCrypto: Registering com/google/android/gms/org/conscrypt/NativeCrypto's 286 native methods...
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
I/ProviderInstaller: Installed default security provider GmsCore_OpenSSL
W/art: Before Android 4.1, method double java.util.concurrent.ThreadLocalRandom.internalNextDouble(double, double) would have incorrectly overridden the package-private method in java.util.Random
    Before Android 4.1, method int java.util.concurrent.ThreadLocalRandom.internalNextInt(int, int) would have incorrectly overridden the package-private method in java.util.Random
    Before Android 4.1, method long java.util.concurrent.ThreadLocalRandom.internalNextLong(long, long) would have incorrectly overridden the package-private method in java.util.Random
  • Please edit your question and add your database structure as a screenshot. Please also add the content of your "Journal" class. – Alex Mamo Feb 03 '21 at 17:19

1 Answers1

1

SimpleDateFormat is used:

  1. to format a java.util.Date into a String
  2. to parse a date-time string into java.util.Date.

In the following line, you are passing a String object to SimpleDateFormat#format:

String journalDate = sdf.format(jDate.getText().toString().trim());

which is not possible because SimpleDateFormat#format requires the parameter to be of type, java.util.Date. You should do it as

SimpleDateFormat sdf=new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);
String journalDate = sdf.format(new SimpleDateFormat("d/M/yyyy", Locale.ENGLISH).parse(jDate.getText().toString().trim()));

i.e. first, you need to parse the text from jDate into java.util.Date and then format it using SimpleDateFormat#format.

Demo:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class Main {
    public static void main(String[] args) throws ParseException {
        // A sample date string
        String strDate = "01/02/2021";

        // Parse the date string into java.util.Date
        SimpleDateFormat sdfInput = new SimpleDateFormat("d/M/yyyy", Locale.ENGLISH);
        Date date = sdfInput.parse(strDate);
        System.out.println(date);

        // Format date into some custom format
        SimpleDateFormat sdfOutput = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
        String formatted = sdfOutput.format(date);
        System.out.println(formatted);
    }
}

Output:

Mon Feb 01 00:00:00 GMT 2021
2021-02-01

The date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.

A demo of the modern date-time API:

import java.text.ParseException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) throws ParseException {
        // A sample date string
        String strDate = "1/2/2021";

        // Parse the date string into java.util.Date
        DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("d/M/u", Locale.ENGLISH);
        LocalDate date = LocalDate.parse(strDate, dtfInput);
        System.out.println(date);

        // Format date into some custom format
        DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("dd/MM/uuuu", Locale.ENGLISH);
        String formatted = dtfOutput.format(date);
        System.out.println(formatted);
    }
}

Learn more about the modern date-time API from Trail: Date Time.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110