LocalDateTime and DateTimeZone.getDefault returning UTC time - android

I am trying to set the date time of a local object. Here is my code:
val date = DateTime() //returns UTC time
val dateTimeZone = DateTimeZone.getDefault() //returns UTC
val localDateTime = LocalDateTime() //returns UTC
My phone settings are set to automatic date time, and my current time zone is Mountain Time.
How can I get the current time in my time zone (the one appearing on my phone)?

If DateTimeZone.getDefault() returns "UTC", that's because the device's default timezone is set to it, so all classes will refer to it unless you specify another zone.
To get the date and time at a specific timezone, you can do:
val date = DateTime(DateTimeZone.forID("America/Denver"))
val localDateTime = LocalDateTime(DateTimeZone.forID("America/Denver"))
Note that America/Denver is just one of the many regions that uses Mountain Time. That's because Joda-Time uses IANA zones names (in the format region/city), so you must choose the best one accordingly from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
Optionally, you can also change the default timezone:
DateTimeZone.setDefault(DateTimeZone.forID("America/Denver"))
With this, just calling LocalDateTime() or DateTime() will use America/Denver as the default zone.
But remind that this will change the default timezone for the whole JVM, so think if that's what you need before doing so.

Related

How to get epoch milis from a date (LocalDate)

I have a month July 2022 for example, I want get epoch milis for the first day of the month
1st July 2022 at midnight.
from the month I was able to get the 1st July 2022, but how to convert it into epoch milis for 1st July 22 midnight
val datey = "July/2020"
val dateFormaty = DateTimeFormatter.ofPattern("MMMM/yyyy")
val yearMonthy = YearMonth.parse(datey, dateFormaty)
val parsedDatey = yearMonthy.atDay(1)
I get 2022-07-01 for parsedDate, I want to get the date time for this date in epoch milis
Thanks
R
Like I mentioned, LocalDate does not actually store any time information whatsoever, so transforming it to epoch isn't possible. Technically. Yet it is with some possible inacuracies.
How about something like this:
make the following extension function
fun LocalDate.toDate(): Date = Date.from(this.atStartOfDay(ZoneId.systemDefault()).toInstant())
Note that it uses the system default timezone for this, to provide the necessary information.
then just use it.
val myDate = myLocalDate.toDate()
which would in your case, be parsedDatey.toDate()
But, we don't really even need the Date here. Lets avoid casting the LocalDate to Date then getting the epoch milli from there, and just do it from the provided Instant instead.
So the real answer to your question is this:
fun LocalDate.getEpochMillis(): long = this.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli()
// call this in your parsing method you posted
parsedDatey.getEpochMillis()

Android - Convert user selected time to UTC and vice versa

I'm working on Android application, and I want to convert user-selected local time (device time) into UTC seconds. After that, I have to convert it again and display in the device's time zone. Can anyone suggest how to do this in Kotlin?
I want to convert user-selected local time (device time) into UTC seconds
You're thinking about this incorrectly. Timestamps, including device time, do not have a time zone. All timestamps are seconds since Jan 1 1970 00:00 UTC, regardless of device time zone. If the user selects a time, and you have that time as a timestamp, it's already in the right format. You can think of it as "UTC seconds," since it's based on a time in UTC, but there's no such thing as timestamps that aren't in such "UTC seconds."
The only time you need a time zone is for converting to a date, displaying it to a user, etc.
Constructs a SimpleDateFormat using the given pattern and the default date format symbols for the default FORMAT locale
fun localToGMT(): Date? {
val date = Date()
val sdf = getDateInstance()
sdf.timeZone = TimeZone.getTimeZone("UTC")
return DateFormat.getDateInstance().parse(sdf.format(date))
}
fun gmttoLocalDate(date: Date):Date? {
val timeZone = Calendar.getInstance().getTimeZone().getID();
val local = Date(date.getTime() + TimeZone.getTimeZone(timeZone).getOffset(date.getTime()));
return local
}

Conversion of date and time to unix timestamp - kotlin

In timestamp variable, I want to get the timestampt value with the current hour, minute and second. The currentDataTime gives me the time in this format: 2020-08-28 17:18:02.
Currently, the timestamp variable returns me 1598645882634 (the last 3 numbers are the miliseconds) but when I convert it in a online conversor to a Human readable format, it gives me 08/28/2020 # 8:18pm (UTC). The only one problem is the hour and minute tha is 3 hours different because of my zone. How can I convert the date AND time to timestamp?
object DateTime {
val currentDataTime: String
#SuppressLint("SimpleDateFormat")
get() {
val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
return dateFormat.format(Date())
}
val timestamp: String
get(){
val formatter: DateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
val date = formatter.parse(currentDataTime) as Date
return date.time.toString().dropLast(3) //it is returning
}
}
A Unix timestamp is defined to be (almost) UTC. It carries no timezone information so it cannot be shifted according to a timezone difference without everything based on it falling apart. (If you'd like to hardwire it anyway, according to your example just add your timezone difference in milliseconds. But read on first.)
Localized time can only be interpreted consistently as long as the proper timezone is attached. It jumps back and forth whenever daylight-savings time starts or ends. If that's not complicated enough, the rules for daylight-savings time may change at any time (and do so around the globe).
Your online converter apparently just took a UTC-based timestamp and displayed it according to your local timezone.
To handle localized date and time values, use the multiplatform date/time library kotlinx-datetime. In the README section Converting an instant to local date and time components you'll find this example:
val currentMoment: Instant = Clock.System.now()
val datetimeInUtc: LocalDateTime = currentMoment.toLocalDateTime(TimeZone.UTC)
val datetimeInSystemZone: LocalDateTime = currentMoment.toLocalDateTime(TimeZone.currentSystemDefault())
There you'll also find elaborate explanations on which type of date and time to use in which scenario.

How to get 2 date objects holding the current time, one in GMT and the other in local

I am trying to fill 2 date objects, one in Local time and the other in UTC.
I AM NOT TRYING TO PRINT THE DATE AS A STRING IN GMT/UTC, please do not suggest DateFormatting, and dont say its a duplicate until you read the full question.
Local, I have no problem:
Date dateLocal = new Date();
The problem is I cant get the utcDate to be UTC.
Using a Calendar like so:
TimeZone utcTimeZone = TimeZone.getTimeZone("UTC");
Calendar c = new GregorianCalendar();
c.setTime(new Date());
c.setTimeZone(TimeZone.getTimeZone(utcTimeZone.getID()));
Date utcDate = c.getTime();
When debugged or submitted to the webservice, utcDate shows in my local timezone, instead of UTC.
Using Joda:
DateTime utcDateTime = DateTime.now(DateTimeZone.UTC);
Date utcDate = utcDateTime.toDate();
Same issue, utcDate when debugged/submitted to webservice is showing in local time.
Here is how the object looks when debugged:
This is an issue because this causes the webservice (which i have no access to) to think this time is UTC, so when it does its work and conversions, the time is always off by 4 hours, since for me the UTC to Local conversion is GMT -4.
The ONLY way i have been able to get this to submit the date in UTC time is by adding:
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
BUT this also changes the LocalTime object, even though this object was defined and set before the default TimeZone was changed.
So i get it, the Date() object uses the JVM locale, so any time a Date is created, its created in the default timezone, and apparently whenever the default timezone is changed, all of the Date objects (even if they are already created) change to the new default timezone... I know Date objects are just the millis between now and 1970 whatever, but the TimeZone is obviously being taken into account in the Webservice and this is messing up my results...how can i get the dates the way i want?

SimpleDateFormat.parse() ignoring timezone?

I am trying to parse date string with timezone using this code for tests:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZZZZZ", Locale.US);
Calendar calendar = Calendar.getInstance();
calendar.setTime(sdf.parse("2017-07-26T06:00-06:00"));
int offset = calendar.getTimeZone().getRawOffset();
I am trying to change timezone from -06 to +09, but offset always contains 10800000.
How to parse date with timezone correctly (I need time and timezone both)?
Note: -06:00 is an offset, not a timezone - those 2 concepts are related, but they are different things (more on that below).
The problem with SimpleDateFormat and Calendar is that they use the system's default timezone, so even though you parse a date with a different offset (like -06:00), the resulting Calendar will have the default timezone (you can check what zone is by calling TimeZone.getDefault()).
That's just one of the many problems and design issues of this old API.
Fortunately, there's a better alternative, if you don't mind adding a dependency to your project (in this case, I think it's totally worth it). In Android you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, you'll also need the ThreeTenABP to make it work (more on how to use it here).
To work with offsets, you can use the org.threeten.bp.OffsetDateTime class:
// parse the String
OffsetDateTime odt = OffsetDateTime.parse("2017-07-26T06:00-06:00");
This will parse all the fields correctly (date/time and offset). To get the offset value, similar to calendar.getTimeZone().getRawOffset(), you can do:
// get offset in milliseconds
int totalSeconds = odt.getOffset().getTotalSeconds() * 1000;
I had to multiply by 1000 because calendar returns the value in milliseconds, but ZoneOffset returns in seconds.
To convert this to another offset (+09:00), it's straightforward:
// convert to +09:00 offset
OffsetDateTime other = odt.withOffsetSameInstant(ZoneOffset.ofHours(9));
As I said, timezone and offset are different things:
offset is the difference from UTC: -06:00 means "6 hours behind UTC" and +09:00 means "9 hours ahead UTC"
timezone is a set of all the different offsets that a region had, has and will have during its history (and also when those changes occur). The most common cases are Daylight Saving Time shifts, when clocks change 1 hour back or forward in a certain region. All these rules about when to change (and what's the offset before and after the change) are encapsulated by the timezone concept.
So, the code above works fine if you're working with offsets and wants to convert to a different one. But if you want to work with a timezone, you must convert the OffsetDateTime to a ZonedDateTime:
// convert to a timezone
ZonedDateTime zdt = odt.atZoneSameInstant(ZoneId.of("Asia/Tokyo"));
// get the offset
totalSeconds = zdt.getOffset().getTotalSeconds() * 1000;
The getOffset() method above will check the history of the specified timezone and get the offset that was active in that corresponding instant (so, if you take a date during DST, for example, the offset (and also date and time) will be adjusted accordingly).
The API uses IANA timezones names (always in the format Region/City, like America/Sao_Paulo or Europe/Berlin).
Avoid using the 3-letter abbreviations (like CST or PST) because they are ambiguous and not standard.
You can get a list of available timezones (and choose the one that fits best your system) by calling ZoneId.getAvailableZoneIds().
You can also use the system's default timezone with ZoneId.systemDefault(), but this can be changed without notice, even at runtime, so it's better to explicity use a specific one.

Categories

Resources