Im using Joda Time to format the dateTime as following:
DateTimeFormatter dateFormatter = DateTimeFormat.longDate();
String startTimeStr = dateFormatter.print(localStartTime);
The variables's values are:
localStartTime={org.joda.time.LocalDateTime#830018681648}"2013-04-06T23:54:35.000"
startTimeStr={java.lang.String#830018688880}"2013年4月6日"
Problem is how could I obtain the locale date format on month and day? I have tried the following codes:
DateTimeFormatter monDayFormatter = DateTimeFormat.forPattern("MMMd");
String startTimeStr = monDayFormatter.print(localStartTime);
and the variables's values are:
localStartTime={org.joda.time.LocalDateTime#830018681648}"2013-04-06T23:54:35.000"
startTimeStr={java.lang.String#830018683220}"4月6"
What I expected startTimeStr is 4月6日. Here the Chinese character 日 = Day.
I do not want to hard code the pattern to "MMMd日", because it should adjust itself according to the current locale information. Any help will be appreciated.
On the website of unicode consortium, you will find in Chinese CLDR repository for example entries like follows (calendar type = gregorian):
<dateFormats>
<dateFormatLength type="full">
<dateFormat>
<pattern>y年M月d日EEEE</pattern>
</dateFormat>
</dateFormatLength>
<dateFormatLength type="long">
<dateFormat>
<pattern>y年M月d日</pattern>
</dateFormat>
</dateFormatLength>
<dateFormatLength type="medium">
<dateFormat>
<pattern>y年M月d日</pattern>
</dateFormat>
</dateFormatLength>
<dateFormatLength type="short">
<dateFormat>
<pattern>yy/M/d</pattern>
</dateFormat>
</dateFormatLength>
</dateFormats>
Internally every localized date format either in JodaTime or in JDK dateformat classes will be translated to such a pattern - including literals like "日". CLDR does not define a month-day-only-format, but this is just a part of a general year-month-day-format, so if you use as replacement for
DateTimeFormatter dateFormatter = DateTimeFormat.longDate().withLocale(Locale.CHINESE);
LocalDateTime localStartTime = new LocalDateTime(2013,4,6,23,54,35);
String startTimeStr = dateFormatter.print(localStartTime);
System.out.println(startTimeStr); // output: 2013年4月6日
this code:
DateTimeFormatter dateFormatter = DateTimeFormat.forPattern("M月d日");
LocalDateTime localStartTime = new LocalDateTime(2013,4,6,23,54,35);
String startTimeStr = dateFormatter.print(localStartTime);
System.out.println(startTimeStr); // output: 4月6日
then you get what you want. Although you write:
I do not want to hard code the pattern to "MMMd日"
that is pretty much the same procedure as done internally by libraries. So the pattern itself is localized by choosing the appropriate literals. There is no way to extract from CLDR a localized date pattern without year. If you want this, then you have to manage your own set of localized month-day-patterns for different locales, maybe in a Map<Locale, String>.
Update from 2016-12-06:
The situation not having a generic month-day-pattern for any locale has not changed for Joda-Time. Unfortunately the official successor of Joda-Time, the JSR-310 (java.time-package) does not manage it well, too, see the JDK-issue 8168532. This was reason enough for me to find a solution for my own time library Time4J in the mean-time. A close analysis of CLDR data has shown that there are other date formats available for many languages, but in a different section and accessible via a group of fields. The keys "Md", "MMMd" and "MMMMd" are relevant for your use-case. Example in Time4J (which should hopefully be supported by JSR-310, too, in a future release):
PlainTimestamp tsp = Iso8601Format.EXTENDED_DATE_TIME.parse("2013-04-06T23:54:35.000");
AnnualDate ad = AnnualDate.of(tsp.getMonth(), tsp.getDayOfMonth());
ChronoFormatter<AnnualDate> chinese =
ChronoFormatter.ofStyle(DisplayMode.LONG, Locale.CHINESE, AnnualDate.chronology());
ChronoFormatter<AnnualDate> english =
ChronoFormatter.ofStyle(DisplayMode.LONG, Locale.ENGLISH, AnnualDate.chronology());
System.out.println(chinese.format(ad)); // 4月6日
System.out.println(english.format(ad)); // Apr 6
It is also worth to note that the locale cannot be changed after construction of formatter in a sensible way because the localized pattern structure will be freezed during construction and is no longer sensible for later changes of locale. This will be improved in future release, however.
Here you go :
Calendar calendar = Calendar.getInstance();
SimpleDateFormat day_week = new SimpleDateFormat("EEEE");
SimpleDateFormat month_date = new SimpleDateFormat("MMMMMMMMM");
Date d = new Date();
String dayOfTheWeek = day_week.format(d);
String month = month_date.format(calendar.getTime());
Hope it helps.
Actually Android provides a helper class to deal with UTS #35 formatting, android.text.format.DateFormat.
In particular for this case, DateFormat.getBestDateTimePattern(locale, skeleton) since API Level 18.
So we can simplify things like this:
String bestFormat = DateFormat.getBestDateTimePattern(Locale.getDefault(), "MMMd");
String formatted = DateFormat.format(bestFormat, System.currentTimeMillis()).toString();
formatted would be "12月19日".
The behavior is confirmed on Android Q and Android O.
Related
I have a String of western date.I want is to have it in Japanese format.
String date = "2015-06-01";
I want is to have it in Japanese format. Please help me!
output = 平成27年6月1日
You can use my lib Time4A which is also available for lower Android API levels and then use its JapaneseCalendar:
String input = "2015-06-01";
PlainDate gregorian = Iso8601Format.EXTENDED_DATE.parse(input);
ChronoFormatter<JapaneseCalendar> f = // immutable, so you can make it static
ChronoFormatter.ofStyle(DisplayMode.MEDIUM, Locale.JAPANESE, JapaneseCalendar.axis());
String output = f.print(gregorian.transform(JapaneseCalendar.axis()));
System.out.println(output); // 平成27年6月1日
I have also done an experiment with the java.time-package which is available since API level 26, but could not quickly find a way to produce the format you want:
DateTimeFormatter dtf =
DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
.withLocale(Locale.JAPAN)
.withChronology(JapaneseChronology.INSTANCE);
JapaneseDate japaneseDate = JapaneseDate.from(LocalDate.parse(input));
System.out.println(dtf.format(japaneseDate)); // H27.06.01
The numbers are correct but it does not use Japanese symbols and letters, despite of the fact that I specified the Japan locale. Maybe a workaround using the builder and a hand-made pattern will help further. Note that my experiment was executed in a Java-8-environment. Maybe Android or newer Java versions are different?!
As a minor supplement to the answer by Meno Hochschild, if you want to use java.time for this, you may do it in this way:
DateTimeFormatter japaneseEraDtf = DateTimeFormatter.ofPattern("GGGGy年M月d日")
.withChronology(JapaneseChronology.INSTANCE)
.withLocale(Locale.JAPAN);
String date = "2015-06-01";
LocalDate gregorianDate = LocalDate.parse(date);
JapaneseDate japaneseDate = JapaneseDate.from(gregorianDate);
System.out.println(japaneseDate.format(japaneseEraDtf));
Output is:
平成27年6月1日
I think it was what you asked for.
If I have understood correctly, java.time does not format the first year of an era in the way usually expected by Japanese, which Meno Hochschild’s Time4A library does, so all things being equal you will prefer his answer.
I have stolen the formatter from this answer by buræquete.
LocalDate localDate = LocalDate.now();
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy/MM/dd").withChronology(IsoChronology.INSTANCE)
.withLocale(Locale.ENGLISH);
DateTimeFormatter japanDateFormat = DateTimeFormatter.ofPattern("yyyy年MM月dd日")
.withChronology(IsoChronology.INSTANCE)
.withLocale(Locale.JAPAN);
}
System.out.println(localDate.format(dateFormat));
System.out.println(localDate.format(japanDateFormat));
Output is:
2022/06/15
2022年06月15日
I got a Problem when converting a Date in my Android App.
My Problem is that I got two different Formats of the Date.
SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
DateFormat formatter_date = new SimpleDateFormat("dd.MMM.yyyy");
Date myDate = null;
try {
myDate = dateFormat.parse("28.10.2015");
} catch (ParseException e) {
e.printStackTrace();
}
formatter_date.format(myDate,"dd.MM.yyyy"))
txtDate.setText(formatter_date.format(myDate,"dd.MM.yyyy")));
I want to have the date formatted as 28.Oct.2015 on a device set to English language, as 28.Okt.2015 in German, etc. So always one dot before and after the month abbreviation. When language is set to English it returns 28.Oct.2015 as it should, however, when Language is set to German it returns 28.Okt..2015 with two dots between Okt and 2015.
Is there any solution to handling this?
I should like to challenge what you are asking for. Of course you can have it, as your own answer already shows. But do you want it?
Use the built-in localized formats
Java has localized formats for all available locales (I think it’s all, in any case it’s many). I suggest you use these rather than your own idea of what a localized date should look like. While 28.Okt.2015 is probably commonplace in Austria and other German-speaking places, English-speaking people are not used to the dots in your format, and I would suspect that some people in the world will find it more or less strange.
I suggested in a comment that you add ThreeTenABP to your Android project in order to use java.time, the modern Java date and time API. It is so much nicer to work with. Now I am taking my own medicine:
DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
LocalDate myDate = LocalDate.of(2015, Month.OCTOBER, 28);
System.out.println(myDate.format(dateFormatter));
Output in different locales include:
German: 28.10.2015
UK English: 28 Oct 2015
French: 28 oct. 2015
It’s not what you asked for. And you may meet objections, but that will happen no matter which format you choose because many people have their own ideas about the proper formatting for their locale. It’s pretty standardized, though, so consider it.
Edit: where did the LocalDate come from?
I understood that you were converting from a string like "28.10.2015". Converting this to a LocalDate is straightforward when you know how:
DateTimeFormatter numericDateFormatter = DateTimeFormatter.ofPattern("dd.MM.uuuu");
LocalDate myDate = LocalDate.parse("28.10.2015", numericDateFormatter);
Only if you got a java.util.Date from a legacy API that you cannot change or do not want to change just now, first thing convert it to the modern Instant type and do further conversions from there:
LocalDate myDate = oldfashionedJavaUtilDate.toInstant()
.atZone(ZoneId.of("Europe/Vienna"))
.toLocalDate();
Since this is a time zone sensitive operation, I recommend you specify an explicit time zone. You may use the JVM’s time zone setting by specifying ZoneId.systemDefault(), but be aware that this is fragile: the JVM setting may be changed under your feet by other parts of your program or other programs running in the same JVM.
What you asked for
The java.time edition of what you asked for is pretty similar to the code in your own answer:
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd");
DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("MMMM");
DateTimeFormatter yearFormatter = DateTimeFormatter.ofPattern("uuuu");
LocalDate myDate = LocalDate.of(2015, Month.OCTOBER, 28);
String dayOfMonth = myDate.format(dateFormatter);
String monthName = myDate.format(monthFormatter);
if (monthName.length() > 3) {
monthName = monthName.substring(0, 3);
}
String year = myDate.format(yearFormatter);
String formattedDate = dayOfMonth + '.' + monthName + '.' + year;
System.out.println(formattedDate);
Output in the same locales as above:
German: 28.Okt.2015
UK English: 28.Oct.2015
French: 28.oct.2015
There is a much shorter way to obtain the same, though:
String formattedDate = String.format("%1$td.%2$.3s.%1$tY",
myDate,
myDate.getMonth().getDisplayName(TextStyle.FULL, Locale.getDefault()));
It’s harder to read. It took me a number of attempts to get the format string %1$td.%2$.3s.%1$tY exactly right. And it will surprise those maintaining your code if they are used to DateTimeFormatter for formatting dates (and times). So I don’t really recommend it, but the choice is yours.
With another date I got the following output in French locale:
08.jui.2018
No French-speaking person, nor anyone else for that matter, will know whether this date was in June (juin) or July (juillet). In 57 of the available locales in my JVM, all 12 months of the year begin with the same three letters. Such locales include Tibetan, Swahili, Somali, Cornish, Scottish Gaelic and Vietnamese. In these languages nobody will be able to tell any months apart. Please think twice.
Links
Oracle tutorial: Date Time, explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.timeto Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
SimpleDateFormat dateFormat = new SimpleDateFormat(String pattern, Locale locale);
has another constructor with Locale change Locale.ENGLISH for date to be set in English. You can check other Locale options. I generally use Locale.getDefault() to display date in user's prefered language.
Thanks for help but this solution works best for me
DateFormat formatter_month = new SimpleDateFormat("MMMM"); //Get Whole Name of Month
DateFormat formatter_day = new SimpleDateFormat("dd."); //Get Day + Dot(2 digits)
DateFormat formatter_year = new SimpleDateFormat(".yyyy"); //Get Dot + Year(4 digits)
String str_date = formatter_day.format(date)+ //Day
formatter_month.format(date).substring(0,3)+ //Month
formatter_year.format(date); //Year
Example, from 1 min ago
i use api and time response result from Api service as:
{
"date_time":"2016-03-10 03:20:30"
}
Please discuss step by step, And if available how can programticly display it in Arabic format
منذ 15 دقيقة
My Code for date in list view adapter
TextView date_time = (TextView) convertView.findViewById(R.id.date_time_list_home);
date_time.setText(m.dateTime());
First, for any date/time manipulation on Android, I highly recommend using the ThreeTenABP library. This is a back port of the Java 8 java.time.* package, circumventing the notoriously disappointing java.util.Date and java.util.Calendar classes.
To parse your "date_time" using this library, you can use the following code:
// I set the ZoneId to systemDefault, but you should really use the ZoneId of the server
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
.withZone(ZoneId.systemDefault());
Instant instant = formatter.parse(m.dateTime(), Instant.FROM);
Android provides the DateUtils class to display date and time information. This class takes into account system settings such as Locale and 12/24-hour format. Therefore, if the Locale of the device is set to any of the Arabic locales (ar_), the date/time will be displayed in a format suited for it.
String display = DateUtils.getRelativeTimeSpanString(
instant.toEpochMilli(),
Instant.now().toEpochMilli(),
DateUtils.MINUTE_IN_MILLIS);
date_time.setText(display);
The last parameter in getRelativeTimeSpanString is the minimum resolution, so setting DateUtils.MINUTE_IN_MILLIS will not display the difference in seconds.
If you insist on using the Java 7 classes, here is the same code using them:
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = format.parse(m.dateTime());
String display = DateUtils.getRelativeTimeSpanString(
date.getTime(),
new Date(),
DateUtils.MINUTE_IN_MILLIS);
date_time.setText(display);
If you need a "transition resolution" greater than a single day (i.e. you want to display a date/time that is further than one day in the past as "… days ago") you can use the DateUtils.getRelativeDateTimeString() method instead:
String display = DateUtils.getRelativeDateTimeString(
mContext,
instant.toEpochMilli(),
DateUtils.MINUTE_IN_MILLIS,
DateUtils.WEEK_IN_MILLIS,
DateUtils.FORMAT_ABBREV_ALL);
Any date that is further back than the transitionResolution (in this case, one week) will be displayed in an appropriate date format, instead of the relative format. The minResolution and transitionResolution can be any long value, DateUtils contains other convenient constants such as MONTH_IN_MILLIS and YEAR_IN_MILLIS.
The last parameter takes an integer for formatting flags. These flags override the default formatting that DateUtils uses for each Locale; view the documentation for more information.
Every time I try to get the current time (I have a button for that, lets call it "botonGuardarEstado") I get the same hours and minutes. What I have noted is that the time I got is the time when I opened the app. What I mean is, if I opened the app at 7:10 a.m. and press the button at 7:12 a.m., I get 7:10 a.m. Here is my code:
DateFormat formatoFecha = new SimpleDateFormat("HH:mm dd/MM/yyyy");
String fecha = formatoFecha.format(Calendar.getInstance().getTime());
I am not getting weird values like different years or anything like that, and the format works well, the problem is that i get the same hours:minutes everytime i push the button. I alredy tried different ways of getting the date and time, things like Date(), or even getting only the hours and minutes using something like this
Calendar cal = Calendar.getInstance();
int mins = cal.get(Calendar.MINUTE);
but still got the same values.
I have the following class
private class InfoArchivo {
String temperatura, humedad, gas, humo, iluminacion, riego, ventilacion, fecha;
public InfoArchivo(String temperatura, String humedad, String gas, String humo, String iluminacion, String riego, String ventilacion, String fecha){
this.temperatura = temperatura;
this.humedad = humedad;
this.gas = gas;
this.humo = humo;
this.iluminacion = iluminacion;
this.riego = riego;
this.fecha = fecha;
if(!ventilacion.equals("0"))
this.ventilacion = "1";
else
this.ventilacion = "0";
}
I have an array of instances of that class. What i am trying to do is write a csv file using the array. Every other data (temperatura, humedad, etc) is correct. The only thing causing trouble is the date (fecha). The creation of the csv file is done until i press another button. When i press the botonGuardarEstado button i get the date, make an instance of the class InfoArchivo and add it to the array
EDIT: Also tried with this but still have the same issue:
Instant instant = Instant.now();
ZoneId zoneId = ZoneId.of("America/Guatemala");
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, zoneId);
DateTimeFormatter formato = DateTimeFormatter.ofPattern("HH:mm dd/MM/yyyy");
String fecha = zdt.format(formato);
Not a date-time problem
Your code as shown is correct.
So your problem must be happening elsewhere in your app. Perhaps you are not correctly feeding the new String (fecha) to the user interface. Or perhaps you need to do something to refresh the display of that new String’s value. We cannot help you further as you did not provide that other code.
java.time
By the way, you are using outmoded classes. The old date-time classes that have proven to be so confusing and troublesome have been supplanted by the java.time framework. See the Oracle Tutorial.
Java 8 and later: The java.time framework is built-in.
Java 7 & 6: Use the backport of java.time.
Android: Use this wrapped version of that backport.
Instant
An Instant is a moment on the timeline in UTC with resolution up to nanoseconds.
Instant instant = Instant.now(); // Current moment in UTC.
Time Zone
Apply a time zone (ZoneId) to get a ZonedDateTime. If you omit the time zone your JVM’s current default time zone is implicitly applied. Better to specify explicitly the desired/expected time zone.
ZoneId zoneId = ZoneId.of( "America/Montreal" ); // Or "Asia/Kolkata", "Europe/Paris", and so on.
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Generating Strings
You can easily generate a String as a textual representation of the date-time value. You can go with a standard format, your own custom format, or an automatically localized format.
ISO 8601
You can call the toString methods to get text formatted using the common and sensible ISO 8601 standard.
String output = instant.toString();
2016-03-19T05:54:01.613Z
Custom format
Or specify your own particular formatting pattern with the DateTimeFormatter class.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "dd/MM/yyyy hh:mm a" );
Specify a Locale for a human language (English, French, etc.) to use in translating the name of day/month and also in defining cultural norms such as the order of year and month and date. Note that Locale has nothing to do with time zone.
formatter = formatter.withLocale( Locale.US ); // Or Locale.CANADA_FRENCH or such.
String output = zdt.format( formatter );
Localizing
Better yet, let java.time do the work of localizing automatically.
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM );
String output = zdt.format( formatter.withLocale( Locale.US ) ); // Or Locale.CANADA_FRENCH and so on.
I have the below code
public Long getEpochTime(String dateToGetItsEpoch) throws ParseException
{
TimeZone timeZone = TimeZone.getTimeZone("UTC");
final String REQUEST_DATE_FORMAT = "dd/MM/yyyy h:m";
DateFormat format = new SimpleDateFormat(REQUEST_DATE_FORMAT);
Date localDate = format.parse(dateToGetItsEpoch);
Calendar cal = Calendar.getInstance(timeZone);
cal.setTime(localDate);
format.setTimeZone(timeZone);
final String utcTime = format.format(cal.getTime());
Date d = cal.getTime();
return d.getTime();
}
If I change the locale of my device to whatever, I always get the UTC time as the return value. Which is correct, however I want to know how is this happening ? How does the device know Which timezone is the date I am giving to it so that it calculates accordingly ?
A Date doesn't have a time zone at all. A SimpleDateFormat does as a default for parsing and formatting; a Calendar does too; a Date doesn't.
Given this sequence of operations:
TimeZone timeZone = TimeZone.getTimeZone("UTC");
DateFormat format = new SimpleDateFormat(REQUEST_DATE_FORMAT);
Date localDate = format.parse(dateToGetItsEpoch);
Calendar cal = Calendar.getInstance(timeZone);
cal.setTime(localDate);
format.setTimeZone(timeZone);
final String utcTime = format.format(cal.getTime());
... you're initially parsing the string using the default time zone of the device, then you're formatting it in UTC. Note that the Calendar part is irrelevant here - you'd get the same result with:
TimeZone timeZone = TimeZone.getTimeZone("UTC");
DateFormat format = new SimpleDateFormat(REQUEST_DATE_FORMAT);
Date date = format.parse(dateToGetItsEpoch);
format.setTimeZone(timeZone);
final String utcTime = format.format(date);
I would personally recommend using Joda Time where possible for date/time work in Java, mind you. It's a much cleaner API than Calendar/Date.
java.time
The Answer by Jon Skeet is correct. Here is some code updated to use the modern java.time classes that have supplanted the troublesome legacy date-time classes.
Formatting pattern
Define a formatting pattern to match your inputs.
By the way, yours is a poor choice of formats. Instead I recommend using the standard ISO 8601 formats designed for exchanging date-time values as text.
12-hour versus 24-hour clock
Your input data or formatting pattern has a flaw. You used lowercase h which means one or two digits for an hour in the 12-hour clock (rather than 24-hour clock, which is uppercase H or HH). So your input makes no sense unless you add some indicator of AM or PM. I will assume you mistakenly omitted this from your Question's code.
Locale locale = Locale.US ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu h:m a" ).withLocale( locale ) ;
LocalDateTime
Parse such strings as LocalDateTime objects, as they lack an indicator of the intended time zone or offset-from-UTC.
String input = "23/01/2020 4:5 PM" ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
ldt.toString(): 2020-01-23T16:05
Moment
The LocalDateTime object we obtained above does not represent a moment, is not a point on the timeline. We have a time of around 4 PM on the 23rd. But we cannot know if this was meant to be 4 PM in Tokyo, Toulouse, or Toledo — all very different moments several hours apart.
To determine a moment, we must know for certain the intended time zone. Then apply that zone as a ZoneId to get a ZonedDateTime. Then we have arrived at a moment.
Locale is not a time zone
locale of my device to whatever
A Locale has nothing to with time zone. A Locale is used for localizing generated text representing a date-time object.
To localize, specify:
FormatStyle to determine how long or abbreviated should the string be.
Locale to determine:
The human language for translation of name of day, name of month, and such.
The cultural norms deciding issues of abbreviation, capitalization, punctuation, separators, and such.
Example:
Locale l = Locale.CANADA_FRENCH ; // Or Locale.US, Locale.JAPAN, etc.
DateTimeFormatter f =
DateTimeFormatter
.ofLocalizedDateTime( FormatStyle.FULL )
.withLocale( l )
;
String output = myZonedDateTime.format( f );
You could have an engineer from Québec who uses the Locale.CANADA_FRENCH for human language and cultural norms, but while visiting in Japan uses Asia/Tokyo time zone for scheduling appointments.
ZonedDateTime
Back to your LocalDateTime object. If you are certain it was meant to represent a moment as seen in the wall-clock time in Tunisia, then apply a time zone of Africa/Tunis.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
You asked:
How does the device know Which timezone is the date I am giving to it so that it calculates accordingly ?
You were using terrible date-time classes that failed to account for the concept of a date-time lacking an indicator of time zone or offset-from-UTC. So technically, your code is a mess, a hack, unavoidable in those days before Joda-Time and its successor, java.time.
I suggest spending no effort on trying to understand that behavior of Date & Calendar. Just move on to using java.time, the industry-leading date-time handling framework.