1
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

public class CalendarFormat {
    public static final String STARTTIME = " 00:00:00";
    public static final String ENDTIME = " 23:59:59";
    public static final String TIME_ZONE_UTC = "UTC";
    public static final String INPUT_DATE_FORMAT = "yyyyMMdd HH:mm:ss";
    public static final String ISO_8601_FORMAT_MILLISECOND = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";


public static void main(String[] args) {
    CalendarFormat.getDateFormat("20210825_20210826", "CST");
}

    public static String mySqlDateFormatInUtc(String date, String time, String inputTimezoneId) {
        final TimeZone utcTimeZone = TimeZone.getTimeZone(CalendarFormat.TIME_ZONE_UTC);
        SimpleDateFormat input = new SimpleDateFormat(INPUT_DATE_FORMAT);
        input.setTimeZone(TimeZone.getTimeZone(inputTimezoneId));
        String dateToBeformatted = date + " " + time;
        SimpleDateFormat output = new SimpleDateFormat(CalendarFormat.ISO_8601_FORMAT_MILLISECOND);
        output.setTimeZone(utcTimeZone);
        String format = null;
        try {
            format = output.format(input.parse(dateToBeformatted));
            System.out.println(format);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return format;
    }
    
    public static String[] getDateFormat(String dateRangeString, String inputTimezoneId) {
        String[] dates = dateRangeString.split("_");
        String from = CalendarFormat.mySqlDateFormatInUtc(dates[0], CalendarFormat.STARTTIME, inputTimezoneId.trim());
        String to = CalendarFormat.mySqlDateFormatInUtc(dates[1], CalendarFormat.ENDTIME, inputTimezoneId.trim());
        dates[0] = from;
        dates[1] = to;
        return dates;
    }
}

This is my class.. here i am changing the time zone CST to UTC so its adding +5 hrs because of its adding 5hrs its changing the date 25-26 to 25-27 .. but i want the output same as 25-26 same even after the time zone conversion... please anyone help me out struck on this issue for 2 days...

for the above code .. output was like this

2021-08-25 T 05:00:00.000Z 2021-08-27 T 04:59:59.000Z

but i want the output as

2021-08-25 T 00:00:00.000Z 2021-08-26 T 23:59:59.000Z

yogesh
  • 27
  • 5
  • 4
    I recommend you don’t use `TimeZone` and `SimpleDateFormat`. Those classes are poorly designed and long outdated, the latter in particular notoriously troublesome. Instead use `ZoneId`, `ZonedDateTime` and `DateTimeFormatter`, all from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Aug 30 '21 at 06:13
  • Does this answer your question? [TimeZoneConversion - CST to UTC](https://stackoverflow.com/questions/54336541/timezoneconversion-cst-to-utc) – Unknown Aug 30 '21 at 06:19
  • 1
    The "Z" in the ISO timestamp stands for the UTC-Timezone, so your output seems logically correct. If you want to keep the face value of the date including closing on "Z", the simplest thing should be "CST" also with "UTC" as you don't do any conversion at this point. Depending what you want to do with the value this might be an undesireable result as you shift the point in time the date refers to. If you provide some background what you want to do with the results we might make better suggestions – Roland Kreuzer Aug 30 '21 at 06:51

2 Answers2

1

Never use the terrible legacy classes Calendar, Date, SimpleDateFormat, etc. They were years ago supplanted by the modern java.time classes.

You’ll find a predefined formatter for your date string input.

CST is not a real time zone. Might mean “Central Standard Time” for the Midwest of North America, but would only be valid for about half the year. Or it might mean “China Standard Time”. Use real time zone names, in format of Continent/Region.

String[] inputs = "20210825_20210826".split( "_" ) ; 
LocalDate date1 = LocalDate.parse( inputs[0] , DateTimeFormatter.BASIC_ISO_DATE ) ;
ZoneId z = ZoneId.of( "America/Chicago" ) ;
ZonedDateTime firstMomentOfDay1 = date1.atStartOfDay( z ) ;

Let java.time determine first moment of day. Days are not necessarily 24 hours long. And days may not start at 00:00.

Do not target last moment of day. In your current approach, you are inadvertently omitting the moments between 23:59:59 and 00:00:00, losing that last second of the day. Instead use half-open approach where the beginning is inclusive and the ending is exclusive. So a day begins with its first moment and runs up to, but does not include, the first moment of the following day.

ZonedDateTime endOfDate1 = date1.plusDays( 1 ).atStartOfDay( z ) ;

You said:

i want the output as 2021-08-25 T 00:00:00.000Z 2021-08-26 T 23:59:59.000Z

That makes no sense. The Z on the end means an offset of zero hours-minutes-seconds from UTC. But you asked for a particular time zone. That time zone uses a time zone several hours behind UTC.

To adjust from your time zone to an offset of zero, extract an Instant.

Instant instant = firstMomentOfDay1.toInstant() ;

All this has been covered many many times already on Stack Overflow. Search to learn more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
0

Your own default time zone is not relevant

You want 20210825 converted to 2021-08-25T05:00:00.000Z. the start of the day in UTC. That’s easy when you know how. Just don’t mix in Central Time or any other time zone. They are not relevant.

Like Basil Bourque I recommend that you use java.time, the modern Java date and time API, for your date and time work.

private static final DateTimeFormatter ISO_8601_FORMAT_MILLISECOND
        = new DateTimeFormatterBuilder().append(DateTimeFormatter.ISO_LOCAL_DATE)
                .appendLiteral('T')
                .appendPattern("HH:mm.ss.SSS")
                .appendOffsetId()
                .toFormatter(Locale.ROOT);

public static String[] getDateFormat(String dateRangeString) {
    String[] dates = dateRangeString.split("_");
    String from = mySqlDateFormatInUtc(
            LocalDate.parse(dates[0], DateTimeFormatter.BASIC_ISO_DATE),
            LocalTime.MIN);
    String to = mySqlDateFormatInUtc(
            LocalDate.parse(dates[1], DateTimeFormatter.BASIC_ISO_DATE),
            LocalTime.MAX);
    dates[0] = from;
    dates[1] = to;
    return dates;
}

public static String mySqlDateFormatInUtc(LocalDate date, LocalTime time) {
    return date.atTime(time).atOffset(ZoneOffset.UTC).format(ISO_8601_FORMAT_MILLISECOND);
}

Let’s try it out:

    String[] result = CalendarFormat.getDateFormat("20210825_20210826");
    System.out.println(Arrays.toString(result));

Output is:

[2021-08-25T00:00.00.000Z, 2021-08-26T23:59.59.999Z]

We can do even better, though:

  1. Don’t format strings for transferring date and time to your database. Transfer proper date-time objects. I don’t know your SQL database nor your database driver, but this probably means transferring the OffsetDateTime that we got from date.atTime(time).atOffset(ZoneOffset.UTC). For example:

        yourPreparedStatement.setObject(1, yourOffsetDateTime);
    
  2. If for some reason you insist on formatting into strings, you probably don’t need the formatter. OffsetDateTime.toString() produces ISO 8601 format. When the milliseconds are 0, they will be left out in accordance with the ISO 8601 standard, so that should still work.

  3. Do not represent the end of the day by 23:59:59. One, it’s wrong, the day does not end until the next day begins 1 second later. Two, you risk having times falling in the gap you have artificially created between the dates, causing mysterious errors in your application. Represent the end of the day by 00:00:00 on the next day and always treat is as exclusive: a date and time belongs to your interval if it is on or after the start and strictly before the end. This will ensure correct limits.

Link

Oracle tutorial: Date Time explaining how to use java.time.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161