import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.icu.text.LocaleDisplayNames;
import android.icu.text.TimeZoneFormat;
import android.icu.text.TimeZoneNames;
import android.icu.util.TimeZone;
import android.os.SystemProperties;
import android.text.BidiFormatter;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextDirectionHeuristics;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.TtsSpan;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.Xml;
import android.view.View;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
import libcore.util.CountryTimeZones;
import libcore.util.CountryZonesFinder;
import libcore.util.TimeZoneFinder;
public class RegionLocalLoLaProcess {
private static final String TAG = "RegionLocalLoLaProcess" + IntelligentlightConst.DEBUG_SUFFIX;
static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
Context mContext;
ParseLatitudeLongitudeXml mParseLatitudeLongitudeXml;
private static RegionLocalLoLaProcess sRegionLocalLoLaProcess = null;
private long[] mSunriseSunset = {7 * 3600 * 1000,18 * 3600 * 1000}; //six clock and eighteen clock
private RegionLocalLoLaProcess(Context context){
mContext = context;
mParseLatitudeLongitudeXml = new ParseLatitudeLongitudeXml();
}
public static RegionLocalLoLaProcess getInstance(Context context){
if(sRegionLocalLoLaProcess == null){
sRegionLocalLoLaProcess = new RegionLocalLoLaProcess(context);
}
return sRegionLocalLoLaProcess;
}
public static RegionLocalLoLaProcess getInstance(){
return sRegionLocalLoLaProcess;
}
public String getPhoneTimeZone(){
String timeZoneId = SystemProperties.get(TIMEZONE_PROPERTY);
return timeZoneId;
}
public long[] getSunriseSunsetByZoneid(String zoneId)
{
String timeZoneId = zoneId;
if(DEBUG_INTELLIGENTLIGHT) {
Slog.d(TAG, "time zone id: " + timeZoneId);
}
String regionId = timeZoneId != null ? IntelligentInstanceManager.getsRegionLocalLoLaProcess().findRegionIdForTzId(timeZoneId) : null;
if(DEBUG_INTELLIGENTLIGHT) {
Slog.d(TAG, "region id: " + regionId + ";timezone id: " + timeZoneId);
}
if(regionId == null || TextUtils.isEmpty(regionId)){
return new long[] {6 * 3600,18 * 3600};
}
String regionName = IntelligentInstanceManager.getsRegionLocalLoLaProcess().getRegionNameByRegionId(regionId);
String gmt = IntelligentInstanceManager.getsRegionLocalLoLaProcess().getGmtTextfromTimezoneId(timeZoneId);
if(DEBUG_INTELLIGENTLIGHT) {
Slog.d(TAG, "regionName: " + regionName + ";GMT text:" + gmt);
}
float zone = IntelligentInstanceManager.getsRegionLocalLoLaProcess().parseZoneFromGmtText(gmt);
double[] latitudeLongitude = IntelligentInstanceManager.getsRegionLocalLoLaProcess().getRegionLatitudeLongitude(regionName);
if(DEBUG_INTELLIGENTLIGHT && latitudeLongitude != null && latitudeLongitude.length > 1){
//longitude <= 180 ,latitude <= 90
Slog.d(TAG,"latitude: " + latitudeLongitude[1] + ";Longitude:" + latitudeLongitude[0] + ";longitude <= 180 ,latitude <= 90");
}
if(latitudeLongitude == null || latitudeLongitude.length < 2){
latitudeLongitude = new double[2];
latitudeLongitude[0] = 0;
latitudeLongitude[1] = 0;
Slog.e(TAG,"get latitude and longtitude fail , use 0 : 0");
return new long[] {6 * 3600,18 * 3600};
}
int[] dawn = SunRiseSetTime.getSunrise(latitudeLongitude[0],latitudeLongitude[1],new GregorianCalendar(),zone);
int[] dusk = SunRiseSetTime.getSunset(latitudeLongitude[0],latitudeLongitude[1],new GregorianCalendar(),zone);
long dawnTime = dawn[0] * 3600 + dawn[1] * 60 + dawn[2];
long duskTime = dusk[0] * 3600 + dusk[1] * 60 + dusk[2];
return new long[] {dawnTime,duskTime};
}
public double[] getRegionLatitudeLongitude(String regionName) {
return mParseLatitudeLongitudeXml.searchLatitudeLongitudeXmlByRegionName(regionName);
}
public long[] getSunriseSunset(){
return mSunriseSunset;
}
public void setSunriseSunset(long sunRise,long sunSet){
mSunriseSunset[0] = sunRise;
mSunriseSunset[1] = sunSet;
}
// second trasfer to 00:00:00
public static String getTime(long second) {
if (second < 10) {
return "00:0" + second;
}
if (second < 60) {
return "00:" + second;
}
if (second < 3600) {
int minute = (int)second / 60;
second = second - minute * 60;
if (minute < 10) {
if (second < 10) {
return "0" + minute + ":0" + second;
}
return "0" + minute + ":" + second;
}
if (second < 10) {
return minute + ":0" + second;
}
return minute + ":" + second;
}
int hour = (int)second / 3600;
int minute = (int)(second - hour * 3600) / 60;
second = second - hour * 3600 - minute * 60;
if (hour < 10) {
if (minute < 10) {
if (second < 10) {
return "0" + hour + ":0" + minute + ":0" + second;
}
return "0" + hour + ":0" + minute + ":" + second;
}
if (second < 10) {
return "0" + hour + minute + ":0" + second;
}
return "0" + hour + minute + ":" + second;
}
if (minute < 10) {
if (second < 10) {
return hour + ":0" + minute + ":0" + second;
}
return hour + ":0" + minute + ":" + second;
}
if (second < 10) {
return hour + minute + ":0" + second;
}
return hour + minute + ":" + second;
}
/**
* @param
* @param
* @return Region set
*/
public Set<String> lookupAllCountryIsoCodes() {
TimeZoneFinder timeZoneFinder = TimeZoneFinder.getInstance();
CountryZonesFinder mCountryZonesFinder = timeZoneFinder.getCountryZonesFinder();
Set<String> mRegionIds = getNormalizedRegionIds(mCountryZonesFinder.lookupAllCountryIsoCodes());
if(IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) {
Slog.d(TAG, "wuyue mRegionIds = " + mRegionIds);
}
return mRegionIds;
}
private static Set<String> getNormalizedRegionIds(List<String> regionIds) {
final Set<String> result = new HashSet<>(regionIds.size());
for (String regionId : regionIds) {
if(IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) {
//Slog.d(TAG, "regionId = " + regionId);
}
result.add(normalizeRegionId(regionId));
}
return Collections.unmodifiableSet(result);
}
// Uppercase ASCII is normalized for the purpose of using ICU API
public static String normalizeRegionId(String regionId) {
return regionId == null ? null : regionId.toUpperCase(Locale.US);
}
/**
* @param timezone id
* @return Region id
*/
public String findRegionIdForTzId(String tzId) {
return findRegionIdForTzId(tzId, getLocaleRegionId());
}
String findRegionIdForTzId(String tzId , String localeRegionId) {
final Set<String> matchedRegions = lookupCountryCodesForZoneId(tzId);
if (matchedRegions.size() == 0) {
return null;
}
if (localeRegionId != null && matchedRegions.contains(localeRegionId)) {
return localeRegionId;
}
return matchedRegions.toArray(new String[matchedRegions.size()])[0];
}
/**
* @param timezone id
* @return Region ids
*/
public Set<String> lookupCountryCodesForZoneId(String tzId) {
if (tzId == null) {
return Collections.emptySet();
}
TimeZoneFinder timeZoneFinder = TimeZoneFinder.getInstance();
CountryZonesFinder mCountryZonesFinder = timeZoneFinder.getCountryZonesFinder();
List<CountryTimeZones> countryTimeZones = mCountryZonesFinder
.lookupCountryTimeZonesForZoneId(tzId);
Set<String> regionIds = new ArraySet<>();
for (CountryTimeZones countryTimeZone : countryTimeZones) {
FilteredCountryTimeZones filteredZones = new FilteredCountryTimeZones(countryTimeZone);
if (filteredZones.getTimeZoneIds().contains(tzId)) {
regionIds.add(filteredZones.getRegionId());
}
}
return regionIds;
}
/**
* @param
* @return local Region id
*/
private String getLocaleRegionId() {
Locale locale = mContext.getResources().getConfiguration().getLocales().get(0);
return locale.getCountry().toUpperCase(Locale.US);
}
private Locale getLocale() {
return mContext.getResources().getConfiguration().getLocales().get(0);
}
/**
* @param Region id
* @return Region Name
*/
public String getRegionNameByRegionId(String regionId) {
//do not change regionId by language
//final LocaleDisplayNames localeDisplayNames = LocaleDisplayNames.getInstance(getLocale());
final LocaleDisplayNames localeDisplayNames = LocaleDisplayNames.getInstance(Locale.US);
String regionName = regionId == null ? null : localeDisplayNames.regionDisplayName(regionId);
if(IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) {
Slog.d(TAG, "regionName id: " + regionName);
}
return regionName;
}
public String getGmtTextfromTimezoneId(String timeZoneId) {
Formatter formatter = new Formatter(Locale.US/*getLocale()*/, new Date());
return formatter.format(timeZoneId);
}
public float parseZoneFromGmtText(String gmt) {
int begin = -1;
int end = -1;
begin = (gmt.indexOf('+') == -1) ? (gmt.indexOf('-')) : (gmt.indexOf('+'));
end = gmt.indexOf(':');
if(end == -1){
Slog.w(TAG,"parseZoneFromGmtText: gmt: " + gmt + "; local is " + getLocale());
end = gmt.indexOf('.');
}
if(begin == -1 || end == -1 || begin > end){
Slog.w(TAG,"parseZoneFromGmtText: failed to parseZone");
return 0;
}
int en = Integer.valueOf(gmt.substring(begin, end));
float deci = Float.valueOf(gmt.substring(end + 1)) / 60;
float zone = en + deci;
if(IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) {
Slog.d(TAG, " zone zone: " + zone);
}
return zone ;
}
/**
* Wrap {@class CountryTimeZones} to filter time zone that are shown in the picker.
*/
public class FilteredCountryTimeZones {
// New timezone list and the meta data of time zone, notUsedAfter, is introduced in Android P
// in 2018. Only show time zone used in or after 2018.
private static final long MIN_USE_DATE_OF_TIMEZONE = 1514764800000L; // 1/1/2018 00:00 UTC
private final CountryTimeZones mCountryTimeZones;
private final List<String> mTimeZoneIds;
public FilteredCountryTimeZones(CountryTimeZones countryTimeZones) {
mCountryTimeZones = countryTimeZones;
List<String> timeZoneIds = countryTimeZones.getTimeZoneMappings().stream()
.filter(timeZoneMapping ->
timeZoneMapping.showInPicker && (timeZoneMapping.notUsedAfter == null
|| timeZoneMapping.notUsedAfter >= MIN_USE_DATE_OF_TIMEZONE))
.map(timeZoneMapping -> timeZoneMapping.timeZoneId)
.collect(Collectors.toList());
mTimeZoneIds = Collections.unmodifiableList(timeZoneIds);
}
public List<String> getTimeZoneIds() {
return mTimeZoneIds;
}
public CountryTimeZones getCountryTimeZones() {
return mCountryTimeZones;
}
public String getRegionId() {
return normalizeRegionId(mCountryTimeZones.getCountryIso());
}
// Uppercase ASCII is normalized for the purpose of using ICU API
public String normalizeRegionId(String regionId) {
return regionId == null ? null : regionId.toUpperCase(Locale.US);
}
}
// public class TimeZoneInfo {
//
// private final String mId;
// private final TimeZone mTimeZone;
// private final String mGenericName;
// private final String mStandardName;
// private final String mDaylightName;
// private final String mExemplarLocation;
// private final CharSequence mGmtOffset;
//
// public TimeZoneInfo(Builder builder) {
// mTimeZone = builder.mTimeZone;
// mId = mTimeZone.getID();
// mGenericName = builder.mGenericName;
// mStandardName = builder.mStandardName;
// mDaylightName = builder.mDaylightName;
// mExemplarLocation = builder.mExemplarLocation;
// mGmtOffset = builder.mGmtOffset;
// }
// }
// Input must be positive. minDigits must be 1 or 2.
private static String formatDigits(int input, int minDigits, String localizedDigits) {
final int tens = input / 10;
final int units = input % 10;
StringBuilder builder = new StringBuilder(minDigits);
if (input >= 10 || minDigits == 2) {
builder.append(localizedDigits.charAt(tens));
}
builder.append(localizedDigits.charAt(units));
return builder.toString();
}
private static void appendWithTtsSpan(SpannableStringBuilder builder, CharSequence content, TtsSpan span) {
int start = builder.length();
builder.append(content);
builder.setSpan(span, start, builder.length(), 0);
}
/**
* Get the GMT offset text label for the given time zone, in the format "GMT-08:00". This will
* also add TTS spans to give hints to the text-to-speech engine for the type of data it is.
*
* @param tzFormatter The timezone formatter to use.
* @param locale The locale which the string is displayed in. This should be the same as the
* locale of the time zone formatter.
* @param tz Time zone to get the GMT offset from.
* @param now The current time, used to tell whether daylight savings is active.
* @return A CharSequence suitable for display as the offset label of {@code tz}.
*/
public static CharSequence getGmtOffsetText(TimeZoneFormat tzFormatter, Locale locale,
java.util.TimeZone tz, Date now) {
final SpannableStringBuilder builder = new SpannableStringBuilder();
final String gmtPattern = tzFormatter.getGMTPattern();
final int placeholderIndex = gmtPattern.indexOf("{0}");
final String gmtPatternPrefix, gmtPatternSuffix;
if (placeholderIndex == -1) {
// Bad pattern. Replace with defaults.
gmtPatternPrefix = "GMT";
gmtPatternSuffix = "";
} else {
gmtPatternPrefix = gmtPattern.substring(0, placeholderIndex);
gmtPatternSuffix = gmtPattern.substring(placeholderIndex + 3); // After the "{0}".
}
if (!gmtPatternPrefix.isEmpty()) {
appendWithTtsSpan(builder, gmtPatternPrefix,
new TtsSpan.TextBuilder(gmtPatternPrefix).build());
}
int offsetMillis = tz.getOffset(now.getTime());
final boolean negative = offsetMillis < 0;
final TimeZoneFormat.GMTOffsetPatternType patternType;
if (negative) {
offsetMillis = -offsetMillis;
patternType = TimeZoneFormat.GMTOffsetPatternType.NEGATIVE_HM;
} else {
patternType = TimeZoneFormat.GMTOffsetPatternType.POSITIVE_HM;
}
final String gmtOffsetPattern = tzFormatter.getGMTOffsetPattern(patternType);
final String localizedDigits = tzFormatter.getGMTOffsetDigits();
final int offsetHours = (int) (offsetMillis / DateUtils.HOUR_IN_MILLIS);
final int offsetMinutes = (int) (offsetMillis / DateUtils.MINUTE_IN_MILLIS);
final int offsetMinutesRemaining = Math.abs(offsetMinutes) % 60;
for (int i = 0; i < gmtOffsetPattern.length(); i++) {
char c = gmtOffsetPattern.charAt(i);
if (c == '+' || c == '-' || c == '\u2212' /* MINUS SIGN */) {
final String sign = String.valueOf(c);
appendWithTtsSpan(builder, sign, new TtsSpan.VerbatimBuilder(sign).build());
} else if (c == 'H' || c == 'm') {
final int numDigits;
if (i + 1 < gmtOffsetPattern.length() && gmtOffsetPattern.charAt(i + 1) == c) {
numDigits = 2;
i++; // Skip the next formatting character.
} else {
numDigits = 1;
}
final int number;
final String unit;
if (c == 'H') {
number = offsetHours;
unit = "hour";
} else { // c == 'm'
number = offsetMinutesRemaining;
unit = "minute";
}
appendWithTtsSpan(builder, formatDigits(number, numDigits, localizedDigits),
new TtsSpan.MeasureBuilder().setNumber(number).setUnit(unit).build());
} else {
builder.append(c);
}
}
if (!gmtPatternSuffix.isEmpty()) {
appendWithTtsSpan(builder, gmtPatternSuffix,
new TtsSpan.TextBuilder(gmtPatternSuffix).build());
}
CharSequence gmtText = new SpannableString(builder);
// Ensure that the "GMT+" stays with the "00:00" even if the digits are RTL.
final BidiFormatter bidiFormatter = BidiFormatter.getInstance();
boolean isRtl = TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL;
gmtText = bidiFormatter.unicodeWrap(gmtText,
isRtl ? TextDirectionHeuristics.RTL : TextDirectionHeuristics.LTR);
if(IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) {
Slog.d(TAG, "gmtText = " + gmtText);
}
return gmtText;
}
public long[] getSunriseSunsetFromGnss(double[] latitudeLongitude){
//get location from local table
String timeZoneId = IntelligentInstanceManager.getsRegionLocalLoLaProcess().getPhoneTimeZone();
String Regionid = IntelligentInstanceManager.getsRegionLocalLoLaProcess().getRegionNameByRegionId(timeZoneId);
String regionId = timeZoneId != null ? IntelligentInstanceManager.getInstance().getsRegionLocalLoLaProcess().findRegionIdForTzId(timeZoneId) : null;
if (DEBUG_INTELLIGENTLIGHT) {
Slog.d(TAG, "region id: " + regionId + ";timezone id: " + timeZoneId);
}
String regionName = IntelligentInstanceManager.getInstance().getsRegionLocalLoLaProcess().getRegionNameByRegionId(regionId);
// String gmt = IntelligentManager.getInstance().getRegionLocalLatLonProcess().getGmtTextfromTimezoneId(timeZoneId);
// if(DEBUG_INTELLIGENTLIGHT) {
// Slog.d(TAG, "regionName: " + regionName + ";GMT text:" + gmt);
// }
if (DEBUG_INTELLIGENTLIGHT && latitudeLongitude != null && latitudeLongitude.length > 1) {
Slog.d(TAG, "Longitude: " + latitudeLongitude[0] + ";latitude:" + latitudeLongitude[1]);
}
String gmt = IntelligentInstanceManager.getInstance().getsRegionLocalLoLaProcess().getGmtTextfromTimezoneId(timeZoneId);
float zone = 0;
if(gmt != null && !gmt.isEmpty()){
int begin = -1;
int end = -1;
begin = (gmt.indexOf('+') == -1) ? (gmt.indexOf('-')) : (gmt.indexOf('+'));
end = gmt.indexOf(':');
try {
zone = Float.valueOf(gmt.substring(begin, end));
zone += Float.valueOf(gmt.substring(end + 1));
}catch (NumberFormatException e){
e.printStackTrace();
zone = Float.MAX_VALUE;
}
if(IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) {
Slog.d(TAG, " zone: " + zone);
}
}
int[] sunrise = SunRiseSetTime.getSunrise(latitudeLongitude[0], latitudeLongitude[1], new GregorianCalendar(),zone);
int[] sunset = SunRiseSetTime.getSunset(latitudeLongitude[0], latitudeLongitude[1], new GregorianCalendar(),zone);
long[] sunriseSunset = {sunrise[0] * 3600 + sunrise[1] * 60 + sunrise[2],sunset[0] * 3600 + sunset[1] * 60 + sunset[2]};
return sunriseSunset;
}
public long[] getSunriseSunsetFromLocal(){
//get location from local table
String timeZoneId = IntelligentInstanceManager.getsRegionLocalLoLaProcess().getPhoneTimeZone();
String regionId = timeZoneId != null ? IntelligentInstanceManager.getsRegionLocalLoLaProcess().findRegionIdForTzId(timeZoneId) : null;
if (DEBUG_INTELLIGENTLIGHT) {
Slog.d(TAG, "region id: " + regionId + ";timezone id: " + timeZoneId);
}
String regionName = IntelligentInstanceManager.getsRegionLocalLoLaProcess().getRegionNameByRegionId(regionId);
// String gmt = IntelligentManager.getInstance().getRegionLocalLatLonProcess().getGmtTextfromTimezoneId(timeZoneId);
// if(DEBUG_INTELLIGENTLIGHT) {
// Slog.d(TAG, "regionName: " + regionName + ";GMT text:" + gmt);
// }
double[] latitudeLongitude = IntelligentInstanceManager.getsRegionLocalLoLaProcess().getRegionLatitudeLongitude(regionName);
if (DEBUG_INTELLIGENTLIGHT && latitudeLongitude != null && latitudeLongitude.length > 1) {
Slog.d(TAG, "Longitude: " + latitudeLongitude[0] + ";latitude:" + latitudeLongitude[1]);
}
String gmt = IntelligentInstanceManager.getsRegionLocalLoLaProcess().getGmtTextfromTimezoneId(timeZoneId);
float zone = 0;
if(gmt != null && !gmt.isEmpty()){
int begin = -1;
int end = -1;
begin = (gmt.indexOf('+') == -1) ? (gmt.indexOf('-')) : (gmt.indexOf('+'));
end = gmt.indexOf(':');
try {
zone = Float.valueOf(gmt.substring(begin, end));
zone += Float.valueOf(gmt.substring(end + 1));
}catch (NumberFormatException e){
e.printStackTrace();
zone = Float.MAX_VALUE;
}
if(IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) {
Slog.d(TAG, " zone: " + zone);
}
}
int[] sunrise = SunRiseSetTime.getSunrise(latitudeLongitude[0], latitudeLongitude[1], new GregorianCalendar(),zone);
int[] sunset = SunRiseSetTime.getSunset(latitudeLongitude[0], latitudeLongitude[1], new GregorianCalendar(),zone);
long[] sunriseSunset = {sunrise[0] * 3600 + sunrise[1] * 60 + sunrise[2],sunset[0] * 3600 + sunset[1] * 60 + sunset[2]};
return sunriseSunset;
}
public class Formatter {
private final Locale mLocale;
private final Date mNow;
private final TimeZoneFormat mTimeZoneFormat;
public Formatter(Locale locale, Date now) {
mLocale = locale;
mNow = now;
mTimeZoneFormat = TimeZoneFormat.getInstance(locale);
}
/**
* @param timeZoneId Olson time zone id
* @return TimeZoneInfo containing time zone names, exemplar locations and GMT offset
*/
public String format(String timeZoneId) {
TimeZone timeZone = TimeZone.getFrozenTimeZone(timeZoneId);
return format(timeZone);
}
/**
* @param timeZone Olson time zone object
* @return TimeZoneInfo containing time zone names, exemplar locations and GMT offset
*/
public String format(TimeZone timeZone) {
final String id = timeZone.getID();
final TimeZoneNames timeZoneNames = mTimeZoneFormat.getTimeZoneNames();
final java.util.TimeZone javaTimeZone = java.util.TimeZone.getTimeZone(id);
final CharSequence gmtOffset = getGmtOffsetText(mTimeZoneFormat, mLocale, javaTimeZone, mNow);
if(IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) {
Slog.d(TAG, "timeZone info timeZone: " + timeZone);
String long_generic = timeZoneNames.getDisplayName(id,
TimeZoneNames.NameType.LONG_GENERIC, mNow.getTime());
Slog.d(TAG, "timeZone info LONG_GENERIC:" + long_generic);
String long_stand = timeZoneNames.getDisplayName(id,
TimeZoneNames.NameType.LONG_STANDARD, mNow.getTime());
Slog.d(TAG, "timeZone info LONG_STANDARD:" + long_stand);
String long_daynight = timeZoneNames.getDisplayName(id,
TimeZoneNames.NameType.LONG_DAYLIGHT, mNow.getTime());
Slog.d(TAG, "timeZone info LONG_DAYLIGHT:" + long_stand);
String example = timeZoneNames.getExemplarLocationName(id);
Slog.d(TAG, "timeZone info example:" + example);
}
Slog.d(TAG,"timeZone info gmtOffset:" + gmtOffset);
return gmtOffset.toString();
}
}
}
接口:
- public String findRegionIdForTzId(String tzId)
根据系统时区id获取系统区域id。
- public String getRegionNameByRegionId(String regionId)
根据区域id 获取区域名字,从而用与从LatitudeLongitude.xml 中找出区域对应的经纬度。
- public String getGmtTextfromTimezoneId(String timeZoneId)
通过时区id 获取时区描述,如GMT+8:00,
- public int parseZoneFromGmtText(String gmt)
如通过GMT+8:00 返回8,通过GMT-8:00 返回 -8
- public double[] getRegionLatitudeLongitude(String regionName)
通过区域名从LatitudeLongitude.xml获内置的取经纬度
- public long[] getmSunriseSunsetByZoneid(String zoneId)
根据时区id 获取日出日落时间,单位是时间s
- public long[] getSunriseSunsetFromLocal()
通过时区从内置表获取
- public long[] getSunriseSunsetFromGnss(double[] latitudeLongitude)
通过经纬度从内置表获取
/* 获取日落日出 */ package com ///https://www.cnblogs.com/hanoi/archive/2012/07/04/2576325.html import android.text.TextUtils; import android.text.format.Time; import android.util.Slog; import java.io.File; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.TimeZone; public class SunRiseSetTime { private static final String TAG = "SunRiseSetTime" + IntelligentlightConst.DEBUG_SUFFIX; private static Properties propt; private static double RAD = 180.0 * 3600 / Math.PI; private static double midDayTime; private static double dawnTime; private enum DayTimeType { SUNRISE, SUNSET, MIDTIME, DAWNTIME, NIGHTTIME, DAYTIME } public static Map<DayTimeType, String> dailyTime(double longitude, double latitude, GregorianCalendar cal, float tz) { return dailyTime(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0, longitude, latitude,tz ); } public static Map<DayTimeType, String> dailyTime(int year, int month, int day, int hour, int min, int sec, double longitude, double latitude, float tz) { Map<DayTimeType, String> map = new HashMap<DayTimeType, String>(); double lo = longitude / 180 * Math.PI; double la = latitude / 180 * Math.PI; System.out.println("" + year + "-" + month + "-" + day); double richu = timeToDouble(year, month, day, hour, min, sec) - 2451544.5; for (int i = 0; i < 10; i++) // richu = sunRiseTime(richu, jd, wd, tz / 24);// 逐步逼近法算10次 richu = sunRiseTime(richu, 0 - lo, la, tz / 24);// 逐步逼近法算10次 // 日出 map.put(DayTimeType.SUNRISE, doubleToStr(richu)); // 日落 map.put(DayTimeType.SUNSET, doubleToStr(midDayTime + midDayTime - richu)); // 中天 map.put(DayTimeType.MIDTIME, doubleToStr(midDayTime)); // 天亮 map.put(DayTimeType.DAWNTIME, doubleToStr(dawnTime)); // 天黑 map.put(DayTimeType.NIGHTTIME, doubleToStr(midDayTime + midDayTime - dawnTime)); // 昼长 map.put(DayTimeType.DAYTIME, doubleToStr((midDayTime - dawnTime) * 2 - 0.5)); return map; } /** * @param date 儒略日平午 * @param lo 地理经度 * @param la 地理纬度 * @param tz 时区 * @return 太阳升起时间 */ public static Double sunRiseTime(double date, double lo, double la, double tz) { date = date - tz; // 太阳黄经以及它的正余弦值 double t = date / 36525; double j = sunHJ(t); // 太阳黄经以及它的正余弦值 double sinJ = Math.sin(j); double cosJ = Math.cos(j); // 其中2*PI*(0.7790572732640 + 1.00273781191135448*jd)恒星时(子午圈位置) double gst = 2 * Math.PI * (0.779057273264 + 1.00273781191135 * date) + (0.014506 + 4612.15739966 * t + 1.39667721 * t * t) / RAD; double E = (84381.406 - 46.836769 * t) / RAD; // 黄赤交角 double a = Math.atan2(sinJ * Math.cos(E), cosJ);// '太阳赤经 double D = Math.asin(Math.sin(E) * sinJ); // 太阳赤纬 double cosH0 = (Math.sin(-50 * 60 / RAD) - Math.sin(la) * Math.sin(D)) / (Math.cos(la) * Math.cos(D)); // 日出的时角计算,地平线下50分 double cosH1 = (Math.sin(-6 * 3600 / RAD) - Math.sin(la) * Math.sin(D)) / (Math.cos(la) * Math.cos(D)); // 天亮的时角计算,地平线下6度,若为航海请改为地平线下12度 // 严格应当区分极昼极夜,本程序不算 if (cosH0 >= 1 || cosH0 <= -1) return -0.5;// 极昼 double H0 = -Math.acos(cosH0); // 升点时角(日出)若去掉负号 就是降点时角,也可以利用中天和升点计算 double H1 = -Math.acos(cosH1); double H = gst - lo - a; // 太阳时角 midDayTime = date - degree(H) / Math.PI / 2 + tz; // 中天时间 dawnTime = date - degree(H - H1) / Math.PI / 2 + tz;// 天亮时间 return date - degree(H - H0) / Math.PI / 2 + tz; // 日出时间,函数返回值 } /** * 保证角度∈(-π,π) * * @param ag * @return ag */ public static Double degree(double ag) { ag = mod(ag, 2 * Math.PI); return ag <= -Math.PI ? ag + 2 * Math.PI : ag > Math.PI ? ag - 2 * Math.PI : ag; } public static Double mod(double num1, double num2) { num2 = Math.abs(num2); // 只是取决于Num1的符号 return num1 >= 0 ? num1 - ((int) (num1 / num2)) * num2 : ((int) (Math.abs(num1) / num2)) * num2 - Math.abs(num1); } /** * @param t 儒略世纪数 * @return 太阳黄经 */ public static Double sunHJ(double t) { t = t + (32.0 * (t + 1.8) * (t + 1.8) - 20) / 86400.0 / 36525.0; // 儒略世纪年数,力学时 double j = 48950621.66 + 6283319653.318 * t + 53 * t * t - 994 + 334166 * Math.cos(4.669257 + 628.307585 * t) + 3489 * Math.cos(4.6261 + 1256.61517 * t) + 2060.6 * Math.cos(2.67823 + 628.307585 * t) * t; return j / 10000000; } /** * 儒略日的计算 * * @param y 年 * @param M 月 * @param d 日 * @param h 小时 * @param m 分 * @param s 秒 * @return int */ public static int timeToDouble(int y, int M, int d, int h, int m, int s) { double time = 0; if (M <= 2) { M += 12; y -= 1; } if (y * 372 + M * 31 + d >= 588829) { time = (int) (y / 100); time = 2 - time + (int) (time / 4); } time += (int) Math.round(365.25 * (y + 4716) + 0.01) + (int) (30.60001 * (M + 1)) + d + (h * 3600 + m * 60 + s) / (24 * 3600) - 1524.5; return (int) Math.round(time); } public static String doubleToStr(double time) { double t = time + 0.5; t = (t - (int) t) * 24; int h = (int) t; t = (t - h) * 60; int m = (int) t; t = (t - m) * 60; int s = (int) t; return h + ":" + m + ":" + s; } public static int[] getPhoneTime(){ Time time = new Time(); time.setToNow(); int year = time.year; int month = time.month; int day = time.monthDay; int hour = time.hour; int minute = time.minute; int sec = time.second; return new int[] {hour,minute,sec}; } public static void getPhoneTimeString(){ //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); String date = sdf.format(new Date()); SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm:ss"); String date2 = sdf.format(System.currentTimeMillis()); } public static String formatTime(long time, String timeZoneName) { time = time * 1000; android.util.Slog.d(IntelligentlightConst.DEBUG_SUFFIX,"time : " + time + ", timezone : " + timeZoneName); SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss"); TimeZone timeZone; if (TextUtils.isEmpty(timeZoneName)) { timeZone = TimeZone.getDefault(); } else { timeZone = TimeZone.getTimeZone(timeZoneName); } formatter.setTimeZone(timeZone); String hms = formatter.format(time); android.util.Slog.d(IntelligentlightConst.DEBUG_SUFFIX,"HH:mm:ss=" + hms); return hms; } public static long getStringToDate(String dateString, String pattern,String timeZoneName) { SimpleDateFormat dateFormat = new SimpleDateFormat(pattern); TimeZone timeZone; if (TextUtils.isEmpty(timeZoneName)) { timeZone = TimeZone.getDefault(); } else { timeZone = TimeZone.getTimeZone(timeZoneName); } dateFormat.setTimeZone(timeZone); Date date = new Date(); try{ date = dateFormat.parse(dateString); } catch(ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } return date.getTime(); } private static String convertSecondToHMS(long second){ long oneDaySecond = 24 * 3600; if(second == oneDaySecond){ return "24:00:00"; } second = second % oneDaySecond; int h = (int)second / 3600; int m = (int)(second % 3600) / 60; int s = (int)(second % 3600) % 60; return "" + h + ":" + m + ":" + s; } private static int[] convertSecondToHMSArray(long second){ int[] hms = new int[3]; long oneDaySecond = 24 * 3600; if(second == oneDaySecond){ hms[0] = 24; hms[1] = 0; hms[2] = 0; return hms; } second = second % oneDaySecond; int h = (int)second / 3600; int m = (int)(second % 3600) / 60; int s = (int)(second % 3600) % 60; hms[0] = h; hms[1] = m; hms[2] = s; return hms; } private static long convertHMSToSecond(String hms){ if(hms == null || hms.isEmpty()) return -1; try { int indexH = hms.indexOf(':'); if (indexH == -1) { return -1; } int valH = Integer.valueOf(hms.substring(0, indexH)); int indexM = hms.indexOf(':', indexH + 1); if (indexM == -1) { return -1; } int valM = Integer.valueOf(hms.substring(indexH + 1, indexM)); if (hms.substring(indexM + 1).isEmpty()) return -1; int valS = Integer.valueOf(hms.substring(indexM + 1)); return valH * 3600 + valM * 60 + valS; }catch(NumberFormatException e){ Slog.e(TAG,"" + e.getStackTrace()); return -1; } } public static int[] getSunrise(double longitude, double latitude, GregorianCalendar cal, float tz){ String hms = dailyTime(longitude,latitude,cal,tz).get(DayTimeType.SUNRISE); if(IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) { Slog.d(TAG,"getSunrise:longitude " + longitude + ";latitude " + latitude + ";tz= " + tz + ";YMD=" + cal.get(Calendar.YEAR) + "-" + cal.get(Calendar.MONTH) + "-" + cal.get(Calendar.DAY_OF_MONTH)); Slog.d(TAG,"hms = " + hms + ",seconds = " + convertHMSToSecond(hms)); } return convertSecondToHMSArray(convertHMSToSecond(hms)); } public static int[] getSunset(double longitude, double latitude, GregorianCalendar cal, float tz){ String hms = dailyTime(longitude,latitude,cal,tz).get(DayTimeType.SUNSET); return convertSecondToHMSArray(convertHMSToSecond(hms)); } public static void main(String[] args) { Map<DayTimeType, String> time = dailyTime(-13.200000, 27.150000, new GregorianCalendar(), 1); for (DayTimeType item : DayTimeType.values()) { System.out.println(" " + item + " " + time.get(item)); } } }
int[] dawn = SunRiseSetTime.getSunrise(latitudeLongitude[0],latitudeLongitude[1],new GregorianCalendar(),zone); int[] dusk = SunRiseSetTime.getSunset(latitudeLongitude[0],latitudeLongitude[1],new GregorianCalendar(),zone); long dawnTime = dawn[0] * 3600 + dawn[1] * 60 + dawn[2]; long duskTime = dusk[0] * 3600 + dusk[1] * 60 + dusk[2];
/*
网络请求
*/
//https://blog.csdn.net/qq_33562996/article/details/80669004 //https://blog.csdn.net/lintax/article/details/70195138 public void sendGet(String path,boolean isToken,String token,HttpsRequestCallback callback) { // String time = Long.toString(SystemClock.elapsedRealtime()); // new Thread(TAG + "-sendGet-" + time){ // @Override // public void run() { // Looper.prepare(); try { URL url = new URL(path); //open request //java.lang.ClassCastException: com.android.okhttp.internal.huc.HttpURLConnectionImpl cannot be cast to javax.net.ssl.HttpsURLConnection HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection(); SSLContext sslContext = getSSLContext(); SSLSocketFactory sslSocketFactory = null; if(sslContext != null) { sslSocketFactory = sslContext.getSocketFactory(); }else{ Slog.w(TAG,"sslContext is null"); } if(sslSocketFactory != null) { httpsURLConnection.setSSLSocketFactory(sslSocketFactory); }else{ Slog.w(TAG,"sslSocketFactory is null"); } httpsURLConnection.setConnectTimeout(CONN_TIME_OUT_MS); httpsURLConnection.setReadTimeout(READ_TIME_OUT_MS); httpsURLConnection.setHostnameVerifier(getHostnameVerifier()); //httpsURLConnection.setDoOutput(true); httpsURLConnection.setRequestMethod("GET"); addHead(isToken,httpsURLConnection,token); // if(IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) { // Map<String, List<String>> heads = httpsURLConnection.getRequestProperties(); // for(String key : heads.keySet()){ // Slog.d(TAG," key :" + key + "; value :" + heads.get(key)); // } // } httpsURLConnection.connect(); //java.net.UnknownHostException: Unable to resolve host "www.baidu.com": No address associated with hostname //Caused by: android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No address associated with hostname) int respCode = httpsURLConnection.getResponseCode(); httpsURLConnection.disconnect(); BufferedReader in = new BufferedReader( new InputStreamReader(httpsURLConnection.getInputStream(), "UTF-8")); String retData = null; String responseData = ""; if (respCode == 200) { while ((in != null) && (retData = in.readLine()) != null) { responseData += retData; } if(in != null) { in.close(); } if(IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) { //Slog.d(TAG, " ciphertext:" + responseData); String decryTextAll = EncryptionUtil.DecryptResponse(responseData); Slog.d(TAG, " decryTextAll:" + decryTextAll); } JSONObject jsonObject = new JSONObject(EncryptionUtil.DecryptResponse(responseData)); int code = jsonObject.optInt("code",-1); String msg = jsonObject.optString("msg","No value for msg"); String data = jsonObject.optString("data","No value for data"); if(code == 0) { if (!isToken) { // byte[] encrypt = EncryptionUtil.encrypt(tokenInfo, EncryptionUtil.getMD5(UUID).substring(0, 16)); // String encryptStr = EncryptionUtil.base64encodeNoWrapToString(encrypt); if(mHttpsStateInfo.mRequestType != HttpsStateInfo.REQUEST_TYPE_GET_TOKEN){ Slog.w(TAG,"warning warning .........logic error attention,maybe return"); } if (callback != null) { callback.onSuccess(code, msg, data); } callCallbacksOnSuccess(code, msg, data); if (IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) { Slog.d(TAG, "getToken : " + data); } return; } synchronized (mHttpsStateInfo) { switch (mHttpsStateInfo.mRequestType){ case HttpsStateInfo.REQUEST_TYPE_GET_LOCKEY:{ JSONObject child = new JSONObject(data); String keyLoc = child.getString("key"); if (IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) { Slog.d(TAG, "keyLoc : " + keyLoc); } if (callback != null) { callback.onSuccess(code, msg, keyLoc); } callCallbacksOnSuccess(code, msg, keyLoc); //IntelligentManager.getInstance().getHttpsRequestHandleThread().sendGetSunMsg(keyLoc); } break; case HttpsStateInfo.REQUEST_TYPE_GET_SUNTIME:{ JSONObject child = new JSONObject(data); String sun = child.getString("sunRise") + ":" + child.getString("sunSet"); if (IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) { Slog.d(TAG, " sunRise;sunSet=" + sun); } if (callback != null) { callback.onSuccess(code, msg, sun); } callCallbacksOnSuccess(code, msg, sun); } break; case HttpsStateInfo.REQUEST_TYPE_GET_TIMEZONE:{ JSONObject child = new JSONObject(data); String timeZone = child.getString("name"); String gmtOffset = child.getString("gmtOffset"); if (IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) { Slog.d(TAG, " timeZone=" + timeZone); } if (callback != null) { callback.onSuccess(code, msg, timeZone); } callCallbacksOnSuccess(code, msg, timeZone); } break; default: { Slog.w(TAG, "sendGet unknow request type " + mHttpsStateInfo.mRequestType); mHttpsStateInfo.mRequestType = HttpsStateInfo.REQUEST_TYPE_INIT; } } } }else if(code == 500){ if(callback != null){ callback.onFailed(code, msg); } callCallbacksOnFailed(code,msg); }else{ Slog.d(TAG,"unkonw code " + code); if(callback != null){ callback.onFailed(code, "unkonw code"); } callCallbacksOnFailed(code,"unkonw code"); } }else if(respCode == 401){ Slog.d(TAG,"Unauthorized"); if(callback != null){ callback.onFailed(respCode, "Unauthorized"); } callCallbacksOnFailed(respCode,"Unauthorized"); }else if(respCode == 500){ Slog.d(TAG,"respCode: " + respCode); JSONObject jsonObject = new JSONObject(EncryptionUtil.DecryptResponse(responseData)); int code = jsonObject.optInt("code",respCode); String msg = jsonObject.optString("msg","local server failed"); if(callback != null){ callback.onFailed(code, msg); } callCallbacksOnFailed(code,msg); } else{ Slog.d(TAG,"respCode: " + respCode); if(callback != null){ callback.onFailed(respCode, " Internal Server Error"); } callCallbacksOnFailed(respCode," Internal Server Error"); } //httpsURLConnection.disconnect(); } catch (MalformedURLException e) { if(callback != null){ callback.onFailed(-1, "MalformedURLException"); } callCallbacksOnFailed(-1, "MalformedURLException"); e.printStackTrace(); } catch (IOException e) { if(callback != null){ callback.onFailed(-1, "IOException"); } callCallbacksOnFailed(-1, "IOException"); e.printStackTrace(); }catch(Exception e){ if(callback != null){ callback.onFailed(-1, "Exception"); } callCallbacksOnFailed(-1, "Exception"); e.printStackTrace(); } // Looper.loop(); // } // }.start(); } public static SSLContext getSSLContext(){ SSLContext context = null; try { CertificateFactory cf = CertificateFactory.getInstance("X.509"); //InputStream in = inputContext.getAssets().open("root.crt"); InputStream in = new BufferedInputStream(new FileInputStream(CRT_PATH)); Certificate ca = null; try { ca = cf.generateCertificate(in); if(IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) { //Slog.d(TAG, "ca= " + ((X509Certificate) ca).getSubjectDN()); } }catch(Exception e){ e.printStackTrace(); } finally { in.close(); } KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); keystore.load(null, null); keystore.setCertificateEntry("ca", ca); String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keystore); // Create an SSLContext that uses our TrustManager context = SSLContext.getInstance("TLS"); context.init(null, tmf.getTrustManagers(), null); } catch (Exception e){ e.printStackTrace(); } return context; } private static String[] VERIFY_HOST_NAME_ARRAY = new String[]{"ai.df.com","ai.iv.com","www.baidu.com"}; public static final HostnameVerifier createInsecureHostnameVerifier() { return new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { if(IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) { Slog.d(TAG, "hostname : " + hostname); } if (TextUtils.isEmpty(hostname)) { return false; } return !Arrays.asList(VERIFY_HOST_NAME_ARRAY).contains(hostname); } }; } public static HostnameVerifier getHostnameVerifier() { return new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }; } public static class StreamTools { public static byte[] readFromStream(InputStream is) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while ((len = is.read(buffer)) != -1) { baos.write(buffer, 0, len); } is.close(); byte[] result = baos.toByteArray(); baos.close(); return result; } } //UUID should the same with EncryptionUtil //private final static String UUID = "05bd1ee674aa8ed94e5006ef9f28b077"; private final static String UUID = EncryptionUtil.UUID; private String fingerPrintId = MD5Util.MD5(Build.FINGERPRINT); public void addHead(boolean isToken,HttpsURLConnection conn,String token){ if(IntelligentlightConst.DEBUG_INTELLIGENTLIGHT) { Slog.d(TAG, "token:" + token + ";" + (!isToken || TextUtils.isEmpty(token))); } conn.addRequestProperty("Content-Type", "application/json"); conn.addRequestProperty("token", !isToken || TextUtils.isEmpty(token) ? "" : token); conn.addRequestProperty("uuid", UUID); conn.addRequestProperty("mccmnc", getMccMnc()); conn.addRequestProperty("deviceName", Build.DEVICE); conn.addRequestProperty("lang", getLang()); conn.addRequestProperty("softwareCompileVersion", Build.VERSION.INCREMENTAL); conn.addRequestProperty("fingerPrintId", fingerPrintId); }