Android system time - android

in my application i need to get current Date and time, every time the user inputs data with it.
I know i can use System.currentTimeMillis(), but it can give me wrong time(because it gives system time, witch can be edited by user)
So i see the only way is to call server for current time, when the user makes data input. but i am not sure that internet connection is always awailable.
Is there any way to get current time (not system time) in android, without using internet connection?

If you don't want system time you need some other source then.
There are a few possibilities that I know:
Get it from web - Internet needed
Get it from router - enabled wifi needed (NTP)
Get it from GPS - GPS fix needed
All of these aren't very helpful I believe. I don't think you can find a way of getting current time without connecting so something externally.
In my opinion you should use system time and assume it's set correctly. When it's not your application shouldn't crash and should gently know user that he has wrong content because of wrong dates ...

I believe there's no way to get the current system time without the timezone.
A good approach would be getting the current system time first
long time= System.currentTimeMillis();
And then getting the correct TimeZone to handle it
Calendar cal = Calendar.getInstance();
TimeZone tz = cal.getTimeZone();

long dateInMillis = System.currentTimeMillis();
String format = "yyyy-MM-dd HH:mm:ss";
final SimpleDateFormat sdf = new SimpleDateFormat(format);
String dateString = sdf.format(new Date(dateInMillis));
Use dateString as your variable which contains current date time as timestamp.

Well, I googled about your topic, and i got logic solution but not tested:
" Use The network-provided values ", in the android phone settings, it;a as shown in the picture bellow:
The screen I show is DateTimeSettings. The checkbox "Use network-provided values" is associated to the shared preference String KEY_AUTO_TIME = "auto_time"; and also to Settings.System.AUTO_TIME
This settings is observed by an observed called mAutoTimeObserver in the 2 network ServiceStateTrackers: GsmServiceStateTracker and CdmaServiceStateTracker.
Both implementations call a method called revertToNitz() when the settings becomes true. Apparently NITZ is the equivalent of NTP in the carrier world.
Bottom line: You can set the time to the value provided by the carrier thanks to revertToNitz(). Unfortunately, I haven't found a mechanism to get the network time. If you really need to do this, I'm afraid, you'll have to copy these ServiceStateTrackers implementations, catch the intent raised by the framework (I suppose), and add a getter to mSavedTime.
For more informations, i suggest you to check this link here

Use the ScheduledExecutorService with scheduleAtFixedRate to send you "clock ticks". If the user initiates an event and the number of accumulated "clock ticks" since the last event doesn't match the time change on the system clock, you're being lied to.
You don't need to know the correct time. You need to know the correct interval. This can be done with any periodic source, even a local one. (Timekeeping is two jobs: a metronome and a labeler for the intervals of the metronome. You don't want the system's labels because they can be made to lie, but the metronome ticks on even if the labels are changed.)
I'd recommend a relatively slow tick rate (<= 1 tick per minute) and rather sloppy comparisons (within 2%, maybe) since the various clocks may not be all that accurate.

Related

How to convert LocalDateTime to UTC and back, without loading zones?

Background
I'm using threetenbp backport for Android (here), to handle various time related data operations.
One of them is to convert a time to a different timezone (current to UTC and back).
I know this is possible if you use something like that:
LocalDateTime now = LocalDateTime.now();
LocalDateTime nowInUtc = now.atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime();
This works just fine, and it's also quite easy to do the opposite.
The problem
I'm trying to avoid initialization of the library, which loads quite a large file of zones into it. I've already figured out how to handle various date/time related operations without this, except this case of converting to UTC and back.
What I got has an error of a whole 1 hour off from the correct conversion.
What I've tried
This is what I've found and tried:
// getting the current time, using current time zone:
Calendar cal = Calendar.getInstance();
LocalDateTime now = LocalDateTime.of(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), cal.get(Calendar.MILLISECOND) * 1000000);
//the conversion itself, which is wrong by 1 hour in my tests:
LocalDateTime alternativeNowInUtc = now.atZone(ZoneOffset.ofTotalSeconds(TimeZone.getDefault().getRawOffset() / 1000)).withZoneSameInstant(ZoneId.ofOffset("UTC", ZoneOffset.ofHours(0))).toLocalDateTime();
The question
What's wrong exactly with what I wrote? How can I get an alternative code for converting the time without initialization of the library?
Given an instance of LocalDateTime as input, how can I convert it from current timezone to UTC, and from UTC to current timezone ?
This is probably happening because your JVM's default timezone is in Daylight Saving Time (DST).
To get the correct offset, you should check if the timezone is in DST and add this to the offset:
Calendar cal = Calendar.getInstance();
TimeZone zone = TimeZone.getDefault();
// if in DST, add the offset, otherwise add zero
int dst = zone.inDaylightTime(cal.getTime()) ? zone.getDSTSavings() : 0;
int offset = (zone.getRawOffset() + dst) / 1000;
LocalDateTime alternativeNowInUtc = now.atZone(ZoneOffset.ofTotalSeconds(offset))
.withZoneSameInstant(ZoneId.ofOffset("UTC", ZoneOffset.ofHours(0)))
.toLocalDateTime();
Another way to create the nowInUtc as a LocalDateTime is to create an Instant from the Calendar:
LocalDateTime nowInUtc = Instant.ofEpochMilli(cal.getTimeInMillis())
.atOffset(ZoneOffset.ofHours(0)).toLocalDateTime();
Actually, you don't need the Calendar at all, just use Instant.now() to get the current instant:
LocalDateTime nowInUtc = Instant.now().atOffset(ZoneOffset.ofHours(0)).toLocalDateTime();
Or, even shorter, use an OffsetDateTime directly:
LocalDateTime nowInUtc = OffsetDateTime.now(ZoneOffset.ofHours(0)).toLocalDateTime();
Not sure if any of those loads timezone data, it's up to you to test.
And I think that the constant ZoneOffset.UTC can be used instead of ZoneOffset.ofHours(0), because it won't load tz data as well (but I haven't tested it).
Final solution
Assuming the default timezone is in Israel (TimeZone.getDefault() is Asia/Jerusalem):
// April 11th 2018, 3 PM (current date/time in Israel)
LocalDateTime now = LocalDateTime.of(2018, 4, 11, 15, 0, 0);
TimeZone zone = TimeZone.getDefault();
// translate DayOfWeek values to Calendar's
int dayOfWeek;
switch (now.getDayOfWeek().getValue()) {
case 7:
dayOfWeek = 1;
break;
default:
dayOfWeek = now.getDayOfWeek().getValue() + 1;
}
// get the offset used in the timezone, at the specified date
int offset = zone.getOffset(1, now.getYear(), now.getMonthValue() - 1,
now.getDayOfMonth(), dayOfWeek, now.getNano() / 1000000);
ZoneOffset tzOffset = ZoneOffset.ofTotalSeconds(offset / 1000);
// convert to UTC
LocalDateTime nowInUtc = now
// conver to timezone's offset
.atOffset(tzOffset)
// convert to UTC
.withOffsetSameInstant(ZoneOffset.UTC)
// get LocalDateTime
.toLocalDateTime();
// convert back to timezone
LocalDateTime localTime = nowInUtc
// first convert to UTC
.atOffset(ZoneOffset.UTC)
// then convert to your timezone's offset
.withOffsetSameInstant(tzOffset)
// then convert to LocalDateTime
.toLocalDateTime();
The answer of carlBjqsd is okay, just awkward and should maybe a little bit clearer.
Why one hour difference
See the final solution of #carlBjqsd: It uses the expression
int offset = zone.getOffset(1, now.getYear(), now.getMonthValue() - 1, now.getDayOfMonth(), dayOfWeek, now.getNano() / 1000000);
instead of
getRawOffset().
That has caused the difference of one hour you observed. Applications have normally no need only to calculate with the raw offset which leaves out the dst-offset for some periods of the year. It is only the total offset which matters in any conversion from local timestamp to UTC and back. The main purpose of the fine-granular differentiation of partial offsets like raw offsets or dst offsets is just proper naming of the zone (shall we call it standard time or not?).
Misleading title of question: "without loading zones"
No, you can never avoid loading zones if you want to convert between local timestamps and UTC using zones. Your real question is rather: How to avoid loading the zones of ThreetenABP and to use/load the zones of the Android platform instead. And your motivation seems to be:
I'm trying to avoid initialization of the library, which loads quite a
large file of zones into it
Well, I have not measured which zone data have more impact on performance. I can only say based on my studies and knowledge of the source code of involved libraries that java.time and ThreetenBP load the whole file TZDB.dat into a binary array cache in memory (as first step) and then pick out the relevant part for a single zone (i.e. interprete a part of the binary data array via deserialization into a set of zone rules and finally a single ZoneId). Old Java platforms instead work with a set of different zi-files (one for each zone), and I suspect that Android zones behave in a similar way (but please correct me if you know that detail better).
If only ONE zone shall be used at all then the traditional approach of using separate zone files might be better but once you want to iterate over all available zones then it is better to have only one zone file at all.
Personally, I think that the performance aspect is neglectable. If you use the Android zones you will also have some loading times, inevitably. In case you really want to speed up the initialization time of ThreetenABP, you should consider to load it in a background thread.
Are Android zones and ThreetenABP zones equivalent?
Generally not. Both timezone repositories might give the same offset for a concrete zone. And often they do so but sometimes there will be differences which are not under your control. Although both timezone repositories use the data of iana.org/tz in final consequence, differences are mainly caused by possible different versions of tzdb-data. And you cannot control which version of zone data exists on the Android platform because this is up to the user of mobile phone how often he/she updates the Android OS. And this is also true for the data of ThreetenABP. You can offer the latest version of your app including the latest version of ThreetenABP but you cannot control if the mobile device user really updates the app.
Other reasons why to care about choosing the proper tz repository?
Beyond performance and initialization times, there is indeed one special scenario which might be interesting for the choice. If the Android OS is somehow old and uses an outdated version of zone rules then some mobile phone users do not update their operating system but manipulate the device clock in order to compensate the wrong timezone data. This way, they still get the correct local times on the mobile phone (in ALL apps).
In this scenario, ThreetenABP does not offer a good solution because combining their correct zone data with wrong device clock will result in wrong local timestamps (annoying the user). This has been a problem for example in Turkey which changed the dst-rules not a long time ago.
Using just the old calendar and timezone API of Android (in the package java.util) can take into account the problem so correct local timestamps are created. However, if an app communicates UTC-times (for example as count of millisecs since 1970-01-01T00Z) to other hosts (for example servers) then the wrong device clock is still a problem.
We could say why bother because the user has done "nonsense" with the device configuration but we also live in real world and should think about how to make even such users happy. So when thinking about a solution I had introduced at least in my calendar library Time4A methods like SystemClock.inPlatformView() which uses the (probably) most actual zone data and obtains the correct UTC clock based on the assumption that the user will at least observe correct local device time (whatever he/she had done to achieve this goal, either by updating the OS or by clock/zone configuration). I am quite happy with avoiding the old calendar and zone API altogether this way. My API even allows to simultaneously use both zone repositories:
Timezone.of("java.util.TimeZone~Asia/Jerusalem") // uses Android data
Timezone.of("Asia/Jerusalem") // uses Time4A data
Maybe you can profit from these ideas when to find/develop suitable helper classes for your usage of ThreetenABP. Time4A is open source.

Getting time in Time format

I am currently trying to work with Location updating.
I've been using the below to work out the time-stamps of when the last update was processed:
String NewLocationTime = DateFormat.getTimeInstance().format(new Date());
However, to work out the difference between two times, I needed to parse it to a Time format. However, for some reason the Android Studio didn't recognize the DateTimeFormatter, and because I don't know in what format the String is going to come up, I am not quite sure what to put in the formatting either.
I believe it would be much easier if I was to be able to get a Time object straight away, so I can use something like:
long diffInMinutes = java.time.Duration.between(dateTime1, dateTime2).toMinutes();
Can anyone tell me how I get the Time object straight away, or why the Android Studio does not recognize the DateTimeFormatter?
Thank you
Use new Date().getTime() and what you get is the time in milliseconds and you can work with it as you want.
You need to use Date and use Date.getTime() for difference calculation. I do though recommend Joda-Time.
Also look at Calendar.
Time an sql aware wrapper around Date and there is no such thing as DateTime or DateTimeFormatter.

How to make simulate time passing in phone

I want to test if a service will still run after lets say, 5 days has passed. I do not want to just set the phone's time, I want the phone to think that the time has passed so that it will get rid of background apps, etc.
How do I do that in adb?
I want the phone to think that the time has passed so that it will
get rid of background apps, etc.
Android can actually finish your application only and not other app.
To get rid of background apps, you can use Task Manager but that's what manual process.
If you have background service running over 5 days, you can actually stop your service, use AlarmManager for it.
As your question is not properly clarified, there could be multiple solution to your problem, of which i have tried to address.
I use the following code in my app to get the current date:
Calendar c = Calendar.getInstance();
System.out.println("Current time => " + c.getTime());
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
AndroidDate = df.format(c.getTime());
Now with that said, all you can do is set the AndroidExpiryDate (string) and set your own date of expiry:
AndroidExpiryDate = "2016-02-28"
Then you can just compare current date (AndroidDate) with expiry date (AndroidExpiryDate ) using if statement:
if ("AndroidDate".equals("AndroidExpiryDate") )
{
//code to get rid of background app
}

GregorianCalendar and SQLite

I'm trying to setup a RPG that will keep track of a virtual time. After some reading GregorianCalendar seems to be the best way to do this but I have some questions and hoping someone with experience could give me some insight.
Here is what I'm trying to do. The game will start in the year 1675 and run for about 30 years. At that point the character will retire if they have survived that long. The character will be able to choose from actions I've preset for them through the coarse of the game. Some actions will be short and take a hour, others may take a week or a month. The real question comes from me using SQLite heavily. I want to save the current time as well as how long an action will take in my database. My first thought when setting this up was, if I want to start the game in Aug 15, 1675 to have my data base with 3 rows, set those fields to 8, 15, 1675. Then also have 2 more columns for the time. Pull these int via cursor and set them with something like
GregorianCalendar time = new GregorianCalendar();
time.set(year, month, date, hour, minute);
I figured I would pull how long an action takes in a similar fashion. Have an int X, and then a string to tell whether this time is in minutes, hours, days etc. Then either add this int to the int pulled from database to add to the calendar directly.
Q: If I add it directly to the calendar how would I pull int values from the calendar to store in database to load at a later time (when the player loads their game)?
Q: If I add it to the int stored in the database and set the calendar with this new int what will happen when I add enough to make the int out of scope for the calendar (Date is set to 31 but I add another day)?
You can convert from the GregorianCalendar object to/from UNIX time for example using getTimeInMillis() setTimeInMillis(). GregorianCalendar also has a roll() method:
Adds the specified amount to the specified field and wraps the value
of the field when it goes beyond the maximum or minimum value for the
current date. Other fields will be adjusted as required to maintain a
consistent date.
I would recommend using Joda Time as a substitute for the (somewhat lacking) standard java date and time utilities. It's much more flexible.
It has functions to do date math, it supports several different calendars (ISO8601, Buddhist, Coptic, Ethiopic, Gregorian, GregorianJulian, Islamic, Julian), has support for intervals, durations and periods. It has built in formatters that let you make your output look like just about anything you wish.
If it were me, I would use Joda and store the date in the native format presented by Joda (I don;t remember what that is right offhand) and then pull it out again and use Joda to do all the date math, as well as having it convert it to whatever calendar you wish to use for display to the user.
Otherwise, it seems to me you'd be re-inventing the wheel.

gps time vs device time

I create a GPS tracking, but when I use DDMS to send coordinate to the emulator and I want to get time of this coordinate through
Date date = new Date(gpsPos.getTime_stamp()); //gpsPos is an obj
gpsPos.setDate_time(date.toString());
The time I got from the function in miliseconds and I converted it to date using date class in java, but the date I got from converted is different from the real date of device.
How can i get the time location equals real time ? any idea? thx
what is the different between date.toString() and date.toGMTString()?
EDIT:
how can we solve it i want my gps time is equal to the real time (logic enough) in order to use it test sth later?
Date(milliSeconds) will create the Date object based on GMT, Date.toString will create a string based on your locale (by default but can be modified). If the milliseconds you used to create the Date object is actually based on your Locale then your time will be off by 4 hours if you're in EDT as an example.

Categories

Resources