1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.libcore.timezone.tzlookup; 18 19 import java.text.DateFormat; 20 import java.text.DecimalFormat; 21 import java.text.ParseException; 22 import java.util.Collection; 23 import java.util.HashSet; 24 import java.util.List; 25 import java.util.Set; 26 import java.util.TimeZone; 27 import java.util.concurrent.TimeUnit; 28 import java.util.function.Predicate; 29 import java.util.regex.Matcher; 30 import java.util.regex.Pattern; 31 import java.util.stream.Collectors; 32 33 /** 34 * Arbitrary static utility methods. 35 */ 36 final class Utils { 37 38 private static final DateFormat UTC_FORMAT; 39 static { 40 UTC_FORMAT = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); 41 UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); 42 } 43 Utils()44 private Utils() {} 45 toUpperCase(List<String> strings)46 static List<String> toUpperCase(List<String> strings) { 47 return strings.stream().map(String::toUpperCase).collect(Collectors.toList()); 48 } 49 parseUtcOffsetToMillis(String utcOffsetString)50 static long parseUtcOffsetToMillis(String utcOffsetString) throws ParseException { 51 Pattern offsetPattern = Pattern.compile("(-?\\d?\\d):(\\d\\d)"); 52 Matcher matcher = offsetPattern.matcher(utcOffsetString); 53 if (!matcher.matches()) { 54 throw new ParseException("Invalid offset string: " + utcOffsetString, 0); 55 } 56 int minutes = Integer.parseInt(matcher.group(2)); 57 if (minutes > 59) { 58 throw new ParseException("Invalid offset string: " + utcOffsetString, 0); 59 } 60 61 long millis = TimeUnit.HOURS.toMillis(Integer.parseInt(matcher.group(1))); 62 long minutesInMillis = TimeUnit.MINUTES.toMillis(minutes); 63 if (millis < 0) { 64 millis -= minutesInMillis; 65 } else { 66 millis += minutesInMillis; 67 } 68 return millis; 69 } 70 toUtcOffsetString(long offsetMillis)71 static String toUtcOffsetString(long offsetMillis) { 72 boolean negative = false; 73 if (offsetMillis < 0) { 74 negative = true; 75 offsetMillis = Math.abs(offsetMillis); 76 } 77 long hours = TimeUnit.MILLISECONDS.toHours(offsetMillis); 78 long minutes = TimeUnit.MILLISECONDS.toMinutes(offsetMillis - TimeUnit.HOURS.toMillis(hours)); 79 DecimalFormat formatter = new DecimalFormat("00"); 80 return (negative ? "-" : "") + formatter.format(hours) + ":" + formatter.format(minutes); 81 } 82 83 /** Returns (a - b) as a new Set. */ subtract(Set<X> a, Set<X> b)84 static <X> Set<X> subtract(Set<X> a, Set<X> b) { 85 Set<X> result = set(a); 86 result.removeAll(b); 87 return result; 88 } 89 allUnique(Collection<X> values)90 static <X> boolean allUnique(Collection<X> values) { 91 Set<X> set = set(values); 92 return values.size() == set.size(); 93 } 94 setEquals(Collection<X> a, Collection<X> b)95 static <X> boolean setEquals(Collection<X> a, Collection<X> b) { 96 Set<X> aSet = set(a); 97 Set<X> bSet = set(b); 98 return aSet.equals(bSet); 99 } 100 set(Collection<X> values)101 static <X> Set<X> set(Collection<X> values) { 102 return new HashSet<>(values); 103 } 104 allLowerCaseAscii(List<String> strings)105 static boolean allLowerCaseAscii(List<String> strings) { 106 Predicate<String> onlyLowerCaseAscii = s -> { 107 for (char c : s.toCharArray()) { 108 if (c < 'a' || c > 'z') { 109 return false; 110 } 111 } 112 return true; 113 }; 114 Predicate<String> nonLowerCaseAscii = onlyLowerCaseAscii.negate(); 115 return !strings.stream().anyMatch(nonLowerCaseAscii); 116 } 117 formatUtc(long timeMillis)118 static String formatUtc(long timeMillis) { 119 return UTC_FORMAT.format(timeMillis); 120 } 121 } 122