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);
}
本文介绍了一个智能光照系统中如何处理时区、经纬度与日出日落时间的关系。系统能够根据设备所在地区的时区ID找到对应区域ID,并进一步获取该区域的名称及经纬度坐标。通过这些信息,系统可以精确计算出特定地点的日出和日落时间,以实现智能化的光照调节。
1254

被折叠的 条评论
为什么被折叠?



