How to combine two date and times into one date and time?

1.2k Views Asked by At

I have two dates with time values. I need to combine date from one and time from another and make third date and time of those.

Here is the JSON:

  "block_times": [
    {
      "id": 63672,
      "name": "One hour blocked time",
      "all_day": false,
      "start_date": "07/07/2020",
      "end_date": "07/07/2020",
      "start_time": "2000-01-01T16:00:00.000-06:00",
      "end_time": "2000-01-01T17:00:00.000-06:00",
      "note": "One hour block time",
      "account_id": 1,
      "service_routes_id": 4502,
      "created_at": "2020-07-07T10:50:30.599-05:00",
      "updated_at": "2020-07-07T10:50:30.599-05:00"
    }
  ]

I need to get date from start_date and I need to get time from start_time and combine them together with date and time value.

I have the following code:

 public static Date convertBlockedTimeToUserTime(String startTimeStr, String startDateStr) {
      SimpleDateFormat dateFormat = new SimpleDateFormat(getDateTimeFormat(), Locale.US);
      SimpleDateFormat startDateFormatInitial = new SimpleDateFormat("MM/dd/yyyy", Locale.US);
      SimpleDateFormat startDateFormatFinal = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
      SimpleDateFormat startTimeFormat = new SimpleDateFormat(getTimeFormat(), Locale.US);
    try {
      String resultStartDate = startDateFormatFinal.format(startDateFormatInitial.parse(startDateStr));
      String resultStartTime = startTimeFormat.format(dateFormat.parse(startTimeStr));
      String result =  resultStartDate+"T"+resultStartTime;
      return dateFormat.parse(result);
    } catch (ParseException e) {
      e.printStackTrace();
      return null;
    }

I get this result: 2020-07-07T11:00:00.000+01:00 and this is wrong since my current time zone is GMT +2, so it should be like this: 2020-07-07T10:00:00.000+02:00.

Can anyone help me to find the problem?

2

There are 2 best solutions below

5
EpicPandaForce On
  "start_date": "07/07/2020",
 "end_date": "07/07/2020",
 "start_time": "2000-01-01T16:00:00.000-06:00",
 "end_time": "2000-01-01T17:00:00.000-06:00",

What a clunky api

Anyways, as usual, you can use the Calendar API to create a date that refers to both.

  SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy", Locale.US);
  SimpleDateFormat timeFormat = new SimpleDateFormat(getDateTimeFormat(), Locale.US); // TODO: parse 2000-01-01T16:00:00.000-06:00

  Date date = dateFormat.parse(startDateString);
  Date time = timeFormat.parse(startTimeString);

  Calendar dateCalendar = Calendar.getInstance();
  dateCalendar.setTimeInMillis(date.getTime());
  
  Calendar timeCalendar = Calendar.getInstance();
  timeCalendar.setTimeInMillis(time.getTime());

  int year = dateCalendar.get(Calendar.YEAR);
  int month = dateCalendar.get(Calendar.MONTH);
  int day = dateCalendar.get(Calendar.DAY_OF_MONTH);

  timeCalendar.set(Calendar.DAY_OF_MONTH, 1);
  timeCalendar.set(Calendar.YEAR, year);
  timeCalendar.set(Calendar.MONTH, month);
  timeCalendar.set(Calendar.DAY_OF_MONTH, day);

  return timeCalendar.getTime();
  

NOTE: there's a chance that parsing the timezone info into java.util.Date is not a good idea, in which case you might want to look into using the java.time.* API, that should be available in AS 4.0 with AGP 4.0.

3
rzwitserloot On

Your API is extremely clunky. As a rule, the java.time package (which, if you're on an ancient java version that doesn't have it, can still be obtained via the backport) is very good at giving you all sorts of types that can represent all sorts of crazy takes on dates and times, and by using the right types to represent things as they are, code works out as a consequence. Time is a very hard concept to get right, so use the best tool available.

import java.time.*;
import java.time.format.*;

class Example {
    private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("dd/MM/yyyy");

    public static void main(String[] args) {
        String inDate = "07/07/2020";
        String inTime = "2000-01-01T16:00:00.000-06:00";
        LocalDate ld = LocalDate.parse(inDate, DATE_FORMAT);
        OffsetTime time = OffsetDateTime.parse(inTime, DateTimeFormatter.ISO_OFFSET_DATE_TIME).toOffsetTime();
        ZonedDateTime target = time.atDate(ld).atZoneSameInstant(ZoneId.systemDefault());
        System.out.println(target);
    }
}

Here we convert your crazy time input first into an OffsetDateTime (because that is what it is; it a full date and time with an offset and not a time zone; a time zone is something like 'amsterdam'; real time zones have different offsets depending on the time of year and can be entirely different depending on century and such. Offsets are what they say they are). We then discard the date part. Then we turn it back into an offset date time by mixing in the date from your date input, and finally we 're-zone' this thing to your preferred zone. In this snippet, I chose 'the system default', which may not be appropriate for a server app, but is probably what you want on android.

Note that this API is inherently confusing. What happens if, say, the inputs are as follows:

        String inDate = "07/07/2020";
        String inTime = "2000-01-01T23:00:00.000-06:00";

Do you then want this output if you were located in Europe, in summer:

2020-07-08T07:00:00.000+02:00

note how that's not actually on the day the input said, because that's how the zones work out.

That's what this snippet does. It's bizarre if you wouldn't want this (after all, it means that you adjust by a full day depending on where your phone's at when the code runs, that sounds bizarre, no?) - but if the zoned date time result must fall on the input date, then you would probably be best off checking at the end if the day is 'wrong' and then use .plusDays or .minusDays to adjust.