1
+ import java.io.File
2
+
3
+ /*
4
+ * Copyright 2019-2024 JetBrains s.r.o. and contributors.
5
+ * Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
6
+ */
7
+
8
+ private val pkg = " package kotlinx.datetime.timezones.tzData"
9
+
10
+ private fun generateByteArrayProperty (tzData : TzData , header : String , propertyName : String ): String = buildString {
11
+ append(header)
12
+ appendLine()
13
+ appendLine()
14
+ appendLine(" /* ${tzData.fullTzNames.joinToString(" , " )} */" )
15
+ append(" internal val $propertyName get() = byteArrayOf(" )
16
+ for (chunk in tzData.data.toList().chunked(16 )) {
17
+ appendLine()
18
+ append(" " )
19
+ val chunkText = chunk.joinToString {
20
+ it.toString().padStart(4 , ' ' )
21
+ } + " ,"
22
+ append(chunkText)
23
+ }
24
+ appendLine()
25
+ append(" )" )
26
+ }
27
+
28
+ private class TzData (val data : ByteArray , val fullTzNames : MutableList <String >)
29
+ private fun loadTzBinaries (
30
+ zoneInfo : File ,
31
+ currentName : String ,
32
+ result : MutableList <TzData >
33
+ ) {
34
+ val zoneName = if (currentName.isEmpty()) zoneInfo.name else " $currentName /${zoneInfo.name} "
35
+ if (zoneInfo.isDirectory) {
36
+ zoneInfo.listFiles()?.forEach {
37
+ loadTzBinaries(it, zoneName, result)
38
+ }
39
+ } else {
40
+ val bytes = zoneInfo.readBytes()
41
+ val foundTzData = result.firstOrNull { it.data.contentEquals(bytes) }
42
+ val tzData: TzData
43
+ if (foundTzData != null ) {
44
+ tzData = foundTzData
45
+ } else {
46
+ tzData = TzData (bytes, mutableListOf ())
47
+ result.add(tzData)
48
+ }
49
+
50
+ tzData.fullTzNames.add(zoneName)
51
+ }
52
+ }
53
+
54
+ fun generateZoneInfosResources (zoneInfoDir : File , outputDir : File , version : String ) {
55
+ val header = buildString {
56
+ appendLine()
57
+ append(" /* AUTOGENERATED FROM ZONE INFO DATABASE v.$version */" )
58
+ appendLine()
59
+ appendLine()
60
+ append(pkg)
61
+ }
62
+
63
+ val loadedZones = mutableListOf<TzData >()
64
+ zoneInfoDir.listFiles()?.forEach { file ->
65
+ loadTzBinaries(file, " " , loadedZones)
66
+ }
67
+
68
+ val zoneDataByNameBody = StringBuilder ()
69
+ val getTimeZonesBody = StringBuilder ()
70
+ loadedZones.forEachIndexed { id, tzData ->
71
+ val tzDataName = " tzData$id "
72
+ val data = generateByteArrayProperty(tzData, header, tzDataName)
73
+ File (outputDir, " $tzDataName .kt" ).writeText(data)
74
+ tzData.fullTzNames.forEach { name ->
75
+ zoneDataByNameBody.appendLine(" \" $name \" -> $tzDataName " )
76
+ getTimeZonesBody.appendLine(" \" $name \" ," )
77
+ }
78
+ }
79
+
80
+ val content = buildString {
81
+ append(header)
82
+ appendLine()
83
+ appendLine()
84
+ appendLine(" internal fun zoneDataByName(name: String): ByteArray = when(name) {" )
85
+ append(zoneDataByNameBody)
86
+ appendLine()
87
+ append(" else -> throw kotlinx.datetime.IllegalTimeZoneException(\" Invalid timezone name\" )" )
88
+ appendLine()
89
+ append(" }" )
90
+ appendLine()
91
+ appendLine()
92
+ append(" internal val timeZones: Set<String> by lazy { setOf(" )
93
+ appendLine()
94
+ append(getTimeZonesBody)
95
+ appendLine()
96
+ append(" )" )
97
+ append(" }" )
98
+ }
99
+
100
+ File (outputDir, " tzData.kt" ).writeText(content)
101
+ }
0 commit comments